purescript-contrib / purescript-book Goto Github PK
View Code? Open in Web Editor NEWThis project forked from paf31/purescript-book
Sources for the PureScript book
Home Page: https://book.purescript.org/
This project forked from paf31/purescript-book
Sources for the PureScript book
Home Page: https://book.purescript.org/
PRs for adding tests:
Open:
Complete:
Skipping:
Contributing:
We could use help with adding tests for the other chapters, so please feel free to assign yourself to any of the open PRs.
Readers are unlikely to be prepared for this exercise based on the previous book content.
Here's a thread describing difficulties: https://discourse.purescript.org/t/ch10-exercise-genericdecode-on-tree/1186
#52 adds some hints, but it would be most ideal to arm the reader with everything they need beforehand. The typeclasses chapter seems like a good place to explain eta-expansion.
In the follow example:
length' :: forall a. Array a -> Int
length' arr = length arr 0
where
length :: forall a. Array a -> Int -> Int
length arr acc =
if null arr
then 0
else length (fromMaybe [] $ tail arr) acc + 1
The two variables a
and arr
in length
shadow declarations from length'
. It might be good to call this out in the text.
@paluh created a guide on this topic, and this material would be great to include in Ch10. I may get around to this after #57 is merged.
Some notes on content:
EffectFn1
is new and useful materialwindow.alert
instead of alert
, even though they are equivalent in most cases.There's an issue link in this section that should be cleared-up once purescript/purescript-st#33 is resolved.
I'd like to see an explanation on how to use Prim.Row in the book.
Details on how to use Variant would also be nice. I think the existing readme could be expanded and either find a new home in the book or be linked to from the book.
Both of these related topics could fill a new chapter.
There's light coverage of row
s in Chapter 5 and Chapter 9, and there used to be some other minor material in Chapter 8 with the older Eff
.
Here's a list of articles on the topic, plus two more: 1 2. I'd like to distill some of this content and put in in the book so beginners don't have to do so much digging for it.
Tagging @drewolson, since this is another idea of a topic to cover.
Would be nice to be able to render to book into a single file (like pdf). I know i can use pandoc, but i think it could use a little more like a Contents section.
Towards the end of the 2nd chapter is the last exercise which is as follows:
spago install
to install the purescript-globals
package as a dependency. Test out its functions in PSCi (Hint: you can use the :browse
command in PSCi to browse the contents of a module).When I do spago install purescript-globals
, it yields the following:
[warn] The package 'purescript-globals' was not found in your package set, but 'globals' was. Using that instead.
[warn] Configuration file was not updated.
[info] Installation complete.
This sent me down a rabbit hole where I realized that bower install purescript-globals
might have been used originally.
In any case, the existing behavior is sufficiently different to be confusing to at least this reader:
globals
is already available at this Purescript version level.Globals
.So I don't know what's expected in this exercise; much of the "connecting information" is missing.
Would the following work better?
spago ls packages
to show where packages are stored in GitHub and what their global names are:
purescript-globals
entry and browse its GitHub entry.:browse
command in PSCi to browse the contents of a module).I'll be glad to do whatever the group decides as a PR.
Hi, the example on how purescript will turn tail recursive functions into js while
loops doesn't actually work as expected.
Code like this:
length_tail :: forall a. Array a -> Int
length_tail arr = len_ arr 0
where
len_ :: forall a. Array a -> Int -> Int
len_ arr acc =
if null arr then
0
else
len_ (fromMaybe [] $ tail arr) acc + 1
Will become your stack overflowing call in javascript:
var length_tail = function (arr) {
var len_ = function (arr1) {
return function (acc) {
var $10 = Data_Array["null"](arr1);
if ($10) {
return 0;
};
return len_(Data_Maybe.fromMaybe([ ])(Data_Array.tail(arr1)))(acc) + 1 | 0;
};
};
return len_(arr)(0);
};
You need to change acc + 1
into (acc + 1)
:
length_tail :: forall a. Array a -> Int
length_tail arr = len_ arr 0
where
len_ :: forall a. Array a -> Int -> Int
len_ arr acc =
if null arr then
0
else
len_ (fromMaybe [] $ tail arr) (acc + 1)
To get the while
loop version:
var length_tail = function (arr) {
var len_ = function ($copy_arr1) {
return function ($copy_acc) {
var $tco_var_arr1 = $copy_arr1;
var $tco_done = false;
var $tco_result;
function $tco_loop(arr1, acc) {
var $10 = Data_Array["null"](arr1);
if ($10) {
$tco_done = true;
return 0;
};
$tco_var_arr1 = Data_Maybe.fromMaybe([ ])(Data_Array.tail(arr1));
$copy_acc = acc + 1 | 0;
return;
};
while (!$tco_done) {
$tco_result = $tco_loop($tco_var_arr1, $copy_acc);
};
return $tco_result;
};
};
return len_(arr)(0);
};
I just started learning purescript, so sorry if I'm missing something here.
This code was written in a project using:
spago
: v0.10.0.0purs
: v0.13.4Chapter 8 required a complete rewrite once 0.12 was released because Effect
replaced the old Eff
Monad. I am personally not very satisfied with my rewrite. It's a tough chapter, and should probably be simplified. Thoughts and suggestions are welcome!
Here's the exercise statement:
(Medium) Write a function
fromSingleton
which uses an array literal pattern to extract the sole member of a singleton array. If the array is not a singleton, your function should return a provided default value. Your function should have typeforall a. a -> Array a -> a
I don't think there's any scenario in which the array literal pattern makes sense. Here are 3 different implementations I explored:
fromSingleton :: ∀ a. a -> Array a -> a
fromSingleton def arr = case uncons arr of
Just { head: x, tail: xs } -> if 0 == length xs then x else def
Nothing -> def
fromSingleton' :: ∀ a. a -> Array a -> a
fromSingleton' def arr
| 1 == length arr = fromMaybe def $ head arr
| otherwise = def
fromSingleton'' :: ∀ a. a -> Array a -> a
fromSingleton'' def [] = def
fromSingleton'' _ [ x ] = x
fromSingleton'' def _ = def
The exercise's clue recommends using the array literal pattern for the sole member of the singleton array. The problem I see is that the sole member never changes to another value, and so there's no need to use an array literal pattern to cache it.
If I'm correct, then this exercise does not successfully demonstrate the array literal pattern and should be deleted or changed.
I welcome "the answer" that I haven't thought of yet. Any takers?
Ignore
So a friend of mine started reading trough the book, and when he got to the getting-started section - which told him to use the logShow function - he was really confused because he got an error (caused by the fact logShow wasn't imported).
So that section already explains importing Math and Prelude so I think we should add another note on importing the logShow function.
Per issue #79
@p2327 and @oldfartdeveloper are discussing here and here.
Edit (May 26 2020): This is simpler now with #154.
Also, see notes on how examples should be tested: #158 (comment)
We can ensure all tests and solutions are in good working order by adding them to our Travis CI job.
I'm envisioning the following steps in the job config:
spago test
in all chapters and monitor error statusSolutions PRs for a few chapters are in #101 and #102, and anyone is free to start working on this issue. Just post your status here so we don't duplicate efforts.
The installation guide shows how to use npm
to install both the PureScript compiler and Spago. However, it never mentions anything about changing the prefix of npm after installing node. Without that, people may install things via sudo
when that isn't necessary.
See my summary of Justin Woo's post on this issue.
After following the step up to the secion Testing Code Using the Interactive Mode, executing
$ spago repl
will throw:
purs repl: PSCi requires the psci-support package.
For help getting started, visit https://github.com/purescript/documentation/blob/master/guides/PSCi.md
spago: callCommand: purs repl ".spago/console/v4.4.0/src/**/*.purs" ".spago/effect/v2.0.1/src/**/*.purs" ".spago/prelude/v4.1.1/src/**/*.purs" ".spago/psci-support/v4.0.0/src/**/*.purs" "src/**/*.purs" "test/**/*.purs" (exit 1): failed
Please add current instructions to load the psci-support package, like so:
spago install psci-support
This code was written on MacOSX Mojave 10.14.6 using:
As PureScript evolves, it may be useful to have tagged versions of this book corresponding to PureScript version.
This is a lower-priority bonus feature.
mdbook allows running code snippets within the book.
It currently only supports rust by sending the code to Rust Playground (their equivalent of Try Purescript!), but it might be possible to switch backends.
This likely requires some changes to Try Purescript.
After reading through it, here's a few issues that come to mind:
I'd like to apply purty
formatting to this repo once a few more improvements are made to the tool. Here's one issue to watch:
There are also some conflicts with #90 where a newline is inserted before each ANCHOR_END
tag.
There's a lot of duplicated information between this guide:
https://github.com/purescript/documentation/blob/master/guides/Getting-Started.md
and the getting-started chapter:
https://book.purescript.org/chapter2.html
It would be great if we could combine both of these into chapter 2, then purescript.org could link directly to ch2 of the book, instead of the first guide.
Follow-up on flawed merge test as described in #59
Assigned to @oldfartdeveloper
Parent task #79
mdbook allows linking code snippets in the text directly to .purs files so the book stays in sync with the code.
An example of how this works is in #89
We should add a replacement for this original ST
exercise:
(Difficult) The following is a simple way to estimate pi: randomly choose a large number
N
of points in the unit square, and count the numbern
which lie in the inscribed circle. An estimate for pi is4n/N
. Use therandom
andST
effects with thefor
function to write a function which estimates pi in this way.
Effect.random
can no longer be blended with ST
, so we can't complete this "Monte Calro Method" exercise.
It is still possible to estimate pi using a grid of points, but it's not as interesting without random
, and the grid method could actually be tackled in ch4 like so:
estimatePi :: Int -> Number
estimatePi r =
let
bigN = r * r
n =
sum do
x <- 1 .. r
y <- 1 .. r
guard $ x * x + y * y < r * r
pure 1
in
(toNumber (4 * n)) / (toNumber bigN)
I'm not sure if adding this to ch4 would be an improvement, since it doesn't test any new language concepts.
It is possible to complete this exercise using Effect.Ref
, but that's covered in Ch9. We could move Ref
content to Ch8.
Some additional information:
ST
may eventually be merged with Effect
purescript/purescript-st#31
Summary of ways to track mutable state:
Control.Monad.ST
- local mutations
Effect.Ref
- global mutations
forE
from Effect
Control.Moad.ST
provides a safe alternative to global mutable variables when mutation is restricted to a local scope."Control.Monad.State
- passing around (technically immutable) state without having to thread parameters through a bunch of functions.
ST
and Ref
.Previous discussion of this issue in #94
"A Virtual Filesystem" part of Chapter 4 mentions (and uses further in PSCi
session) a FileOperations
module. FileOperations
is not present in excercises/chapter4 directory at the moment. Would that make sense to "pre-populate" this file with an empty module asking the user to implement methods mentioned in the content of the book?
As discussed in #61, these package prefixes are unnecessary (and warned against) when installing via spago.
What are maintainers thoughts on stripping out all purescript-
prefixes from packages mentioned in the book text?
I think all packages can be assumed to be part of the purescript ecosystem unless otherwise specified (eg, "request
module via NPM" in ch12).
Originally proposed by @s0kil in #48 (comment)
Theme from the original file can be viewed in diff of #123
Spago https://github.com/spacchetti/spago seems to have become popular for PureScript projects
I'm questioning the benefits of wrapping record types in newtype
. It doesn't seem to be required for anything except custom Show
instances, which seem to just mimic the default record show.
This is a major annoyance in Chapter 8 (example still in progress to be merged back in), but affects other chapters as well. So a few chapters will need to be modified if this simplification of removing newtype
is applied.
Here's a summary of the dilemma. Note that this situation is partially improved by using separate state for each field, but it would be even simpler with a single person state and no newtype
wrapping, and we should strive for simplicity for our beginner readers.
I find myself doing this:
pp@(Person p@{ homeAddress: Address a }) /\ setPerson <- useState examplePerson
setPerson \_ -> Person p { homeAddress = Address a { street = s } }
When I'd rather do this:
person /\ setPerson <- useState examplePerson
setPerson \_ -> person { homeAddress { street = s } }
Here are the wrapped records for reference:
newtype Person = Person
{ homeAddress :: Address
}
newtype Address = Address
{ street :: String
}
I'd rather just use basic records:
type Person =
{ homeAddress :: Address
}
type Address =
{ street :: String
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.