paf31 / purescript-book Goto Github PK
View Code? Open in Web Editor NEWSources for the PureScript book
Sources for the PureScript book
Let’s also test showEntry by creating an address book entry record containing our example address:
> let entry = { firstName: "John", lastName: "Smith", address: address }
A little later.. but example
has never been defined
> :type insertEntry example
AddressBook -> AddressBook
So instead we get an error. Then I try using entry
(the "example" entry defined earlier)
> :type insertEntry entry
List
{ firstName :: String
, lastName :: String
, address :: { street :: String
, city :: String
, state :: String
}
}
-> List
{ firstName :: String
, lastName :: String
, address :: { street :: String
, city :: String
, state :: String
}
}
Why do I get List
and not AddressBook
!?
For example, this line (https://github.com/paf31/purescript-book/blob/master/chapter9/src/Rectangle.purs#L8) doesn't work anymore, because getCanvasElementById uses Maybe.
getCanvasElementById :: forall eff. String -> Eff (canvas :: Canvas | eff) (Maybe CanvasElement)
I'm told I need to install the purescript-psci-support
package. So I execute that install command yet, it still tells me to install it.
$ psci
PSCi requires the psci-support package to be installed.
You can install it using Bower as follows:
bower i purescript-psci-support --save-dev
Or using psc-package:
psc-package install psci-support
For help getting started, visit http://wiki.purescript.org/PSCi
✘-1 ~/repos/pure-apps/purescript-book/chapter3 [0.10|…1]
12:11 $ bower i purescript-psci-support --save-dev
bower purescript-psci-support#* cached https://github.com/purescript/purescript-psci-support.git#2.0.0
bower purescript-psci-support#* validate 2.0.0 against https://github.com/purescript/purescript-psci-support.git#*
✔ ~/repos/pure-apps/purescript-book/chapter3 [0.10|…1]
12:12 $ psci
PSCi requires the psci-support package to be installed.
You can install it using Bower as follows:
bower i purescript-psci-support --save-dev
Or using psc-package:
psc-package install psci-support
For help getting started, visit http://wiki.purescript.org/PSCi
Ah, I need to execute it via pulp psci
- why not make psci an executable/alias?
and uses an infix operator alias
\/
to compute the union of the two bounding rectangles.
I ended up trying to find that \/
infix operator on pursuit here but I don't think this is the right operator for it's use here.
Hi, I'm following this book using Purescript 0.8.3.0 installed via npm
(Debian).
Chapter 3 defines the following function https://github.com/paf31/purescript-book/blob/master/chapter3/src/Data/AddressBook.purs#L34
insertEntry entry book = Cons entry book
but fails with Unknown data constructor Cons
. Checking purescript's changelog https://github.com/purescript/purescript/releases/tag/v0.8.2 it suggests to me that the new way of expressing this should be
insertEntry entry book = entry : book
or
insertEntry = (:)
Is this correct or I am missing something with Cons
?
Section 8.2 says "The source code for this project builds on the source for the previous chapter, and as such, uses the Grunt build script to include its source files."
Later the book instructs the reader to "... build with Grunt, and open the html/index.html file in your web browser."
I don't see any Gruntfile in the repo. Is this text outdated or is the reader meant to write their own Gruntfile?
In section 5.5, the gcd
function doesn't work, the type is Number -> Number -> Number
, but the definition uses an Int literal.
similarly, the showPicture
example in 5.15 uses Int
literals, I guess it should be
showPicture [Line (Point { x: 0.0, y: 0.0 }) (Point { x: 1.0, y: 1.0 })]
I wouldn't be surprised if there's more of these, those are the two I've found.
section 7.4
For functions of two arguments, we have a curried function f with type a -> b -> c, say. This is equivalent to the type a -> (b -> c), so we can apply map to f to get a new function of type f a -> f (b -> c). Partially applying this function to the first lifted argument (of type f a), we get a new wrapped function of type f (b -> c). We can then use apply to apply the second lifted argument (of type f b) to get our final value of type f c.
Putting this all together, we see that if we have values x :: f a and y :: f b, then the expression (f <$> x) <> y has type f c (remember, this expression is equivalent to apply (map f x) y). The precedence rules defined in the Prelude allow us to remove the parentheses: f <$> x <> y.
> :type flip
forall a b c. (a -> b -> c) -> b -> a -> c
The keyword forall
here indicates that flip has a universally quantified type. It means that we can substitute any types for a, b and c, and flip will work with those types.
Also what does c.
mean? ie, what does the postfix .
signify?
So it looks like an understanding of predicate types/logic is assumed?
Universal quantification
is normally written as ∀
, which you can read as "for all", and means roughly what it sounds like: in a logical statement resembling "∀x. ..." whatever is in place of the "..." is true for all possible "x" you could choose from whatever set of things is being quantified over.
http://stackoverflow.com/questions/14299638/existential-vs-universally-quantified-types-in-haskell
So, a universally quantified type like forall a. a -> a
means that, for any possible type "a", we can implement a function whose type is a -> a
. And indeed we can:
Some of the possible buggy things I observed. Just for your reference.
par
function is used but current purescript-parallel
package don't have such interface anymore as I found. It might be misleading.class (Applicative f, Plus f) <= Alternative f where
, which ends up with a strange where
Control.Monad.Identity
module, but it doesn't exist now. It should be Data.Identity
I think.I hope these can help you. BYW, this is an excellent book!
The following command is roughly the same as https://leanpub.com/purescript/read#leanpub-auto-the-eff-monad-1, but failed like this:
qs@BF:~/../chapter8$ pulp build -O --to dist/Main.js
* Building project in /home/qs/Data/Documents/SourceCode/PureScript/purescript-book/chapter8
* Build successful.
* Bundling Javascript...
events.js:85
throw er; // Unhandled 'error' event
^
Error: ENOENT, open 'dist/Main.js'
at Error (native)
However the following succeeded without any problem.
qs@BF:~/../chapter8$ pulp build -O --to Main.js
* Building project in /home/qs/Data/Documents/SourceCode/PureScript/purescript-book/chapter8
* Build successful.
* Bundling Javascript...
* Bundled.
And if I modify the html/index.html
to point to Main.js
, the web page functions as expected.
Hullo!
The third exercise at the end of chapter 8 makes reference to a Data.AddressBook.UI, but I don't think that file needs to exist anymore! I guess this question needs removing?
Getting the following errors running grunt
Running "psc:all" (psc) task
>> Error creating file dist/Main.js
>>
Warning: Multiple errors:
Error at bower_components/purescript-monoid/src/Data/Monoid/Additive.purs line 48, column 1 - line 51, column 1:
Error in module Data.Monoid.Additive
Unknown type class 'Semiring'
Error at bower_components/purescript-monoid/src/Data/Monoid/Additive.purs line 51, column 1 - line 52, column 21:
Error in module Data.Monoid.Additive
Unknown type class 'Semiring' Use --force to continue.
Aborted due to warnings.
Have tried cleaning and re-installing bower dependancies. Any help is appreciated
Ran into an issue with trying to build chapter 7
cd C:\chapter7
bower update
pulp build
I got the following error message
Error found:
in module Data.AddressBook.Validation
at C:\chapter7\src\Data\AddressBook\Validation.purs line 31, column 3 - line 38, column 6
Could not match type
{ unicode :: Boolean
, sticky :: Boolean
, multiline :: Boolean
, ignoreCase :: Boolean
, global :: Boolean
}
with type
RegexFlags
while checking that type { unicode :: Boolean
, sticky :: Boolean
, multiline :: Boolean
, ignoreCase :: Boolean
, global :: Boolean
}
is at least as general as type RegexFlags
while checking that expression { unicode: false
, sticky: false
, multiline: false
, ignoreCase: false
, global: false
}
has type RegexFlags
in value declaration phoneNumberRegex
See https://github.com/purescript/purescript/wiki/Error-Code-TypesDoNotUnify for more information,
or to contribute content related to this error.
* ERROR: Subcommand terminated with exit code 1
I hadn't altered anything and there isn't a type definition in the module for the "RegexFlags" type to work off of debugging. Could this be a setup issue on my side of things?
Really great read so far!
Edit: Figured it'd be easier just to update one issue rather than make a new one for each item
This is the first section I found a bit confusing. It doesn't seem related to pattern matching at first and a few concepts, emptyBounds
, shapeBounds
, and \/
, were opaque until I looked at the Exercise code.
Perhaps include more code from https://github.com/paf31/purescript-book/blob/master/exercises/chapter5/src/Data/Picture.purs?
Might be nice to introduce uncons or share the motivation--I'm guessing this is to avoid the unsafePartial
s that we've seen until now. e.g.
main :: forall e. Eff (console :: CONSOLE | e) Unit
main = void do
let test = String.uncons "hello world"
case test of
Just y -> log $ show y.head
Nothing -> pure unit
This functional dependency tells the compiler that there is a function from stream types to (unique) element types, so if the compiler knows the stream type, then it can commit to the element type.
This seems at odds with instance streamArray :: Stream (Array a) a
, where the stream does not give us a unique element.
purescript-arrays
is now needed to import Data.Array
src/Data/Hashable.purs
._.head
is equivalent to \x -> x.head
, but would be nice to knowclass Eq a <= Ord a
to clarify3.2 Project Setup https://leanpub.com/purescript/read#leanpub-auto-project-setup
import Control.Plus (empty)
requires purescript-control
.import Data.Maybe (Maybe)
should depends directly on purescript-maybe
.exercises/chapter3/bower.json
],
"dependencies": {
"purescript-lists": "^3.0.0",
- "purescript-console": "^2.0.0"
+ "purescript-console": "^2.0.0",
+ "purescript-control": "^2.0.0",
+ "purescript-maybe": "^2.0.1"
},
"devDependencies": {
"purescript-psci-support": "^2.0.0"
import Control.Plus (empty)
I'm told it is an unknown module. So I guess it is a dependency I need to install!?
I'm getting
at canvas/src/Example/Random.purs line 16, column 1 - line 37, column 20
The last statement in a 'do' block must be an expression, but this block ends with a let binding.
from the Example.Random code at 9.5.
While building the code in Chapter 10 using grunt, I have errors regarding Data.Monoid.Additive module : "Unknown type Semiring" (line 48 and 51)
Hello,
I was working on the Chapter 3, but the compilation doesn't work related to an error in the purescript-foldable-trasversal module :
Warning: Error at bower_components/purescript-foldable-traversable/src/Data/Foldable.purs line 6, column 1 - line 7, column 1:
Error in module Data.Foldable
Cannot import unknown module 'Data.Eq' Use --force to continue.
I guess it's related to this issue : purescript/purescript#769
Do you have any solution to fix that ?
It should probably look like this:
class Monoid m <= Action m a where
act :: m -> a -> a
However it comes out like this:
class Monoid m <= Action m a where
act :: m -> a -> a
Similarly with the other two examples.
Browser: Firefox 50.0, macOS Sierra
At the fork / branch "update-0.10.2" you will find updates of all chapters to latest 0.10.2
.
Commits overview: https://github.com/sectore/purescript-book/commits/update-0.10.2
P.S. purescript-book
does not accept any pull request , right?
-Jens
Please add full working examples for Fact
, Fib
and Reverse
introduces in Chapter 4
module Fact where
import Prelude
fact :: Int -> Int
fact 0 = 1
fact n = n * fact (n - 1)
module Fib where
import Prelude
fib :: Int -> Int
fib 0 = 1
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)
Reverse (attempt)
module Reverse where
import Prelude
import Data.Array
import Partial.Unsafe
reverse :: forall a. Array a -> Array a
reverse [] = []
reverse xs = snoc (reverse (unsafePartial tail xs))
(unsafePartial head xs)
For reverse I get:
Could not match type
Maybe
with type
Array
while trying to match type Maybe (Array t1)
with type Array t0
while checking that expression (unsafePartial tail) xs
has type Array t0
in binding group reverse
Please advice. Thanks.
It seems that chapter 11 depends on having already done:
npm install yargs
But there isn't anything in the book and I'm not quite sure why it's necessary. I know at least one other user had this problem as well:
http://ircbrowse.net/browse/purescript?id=4302×tamp=1414361749#t1414361749
While working my way through the book, using the latest 9.1 version of Purescript, I noticed I had to install two additional dependencies that weren't documented in the book for Chapter 3 . Not sure if this is the right place to suggest fixes to the book or not but here they are:
bower install purescript-control
bower install purescript-lists
In order for these two imports to work:
import Control.Plus (empty)
import Data.List (List(..), filter, head)
I believe they were separated into their own libraries recently.
Thanks for writing the book, it's been very helpful.
λ ~ $ pulp --version
Pulp version 8.1.1
psc version 0.8.4.0 using /usr/local/bin/psc
Tentative fix: https://github.com/raduom/purescript-book/commit/13d086169c2b5be36bca0f0eff79566ac3a5e4f9
Looks like the code should be updated for PureScript 0.9.1.
It isn't very clear in the book that an additional dependency is needed. Also it seems that pulp currently fails to install this module due to some conflicting dependencies.
I get the following error.
grunt [master]
Running "psc:all" (psc) task
>> Error creating file dist/Main.js
>>
Warning: Error at bower_components/purescript-lists/src/Control/Monad/ListT.purs line 41, column 3:
Error in module Control.Monad.ListT
Cannot import unknown module 'Test.QuickCheck' Use --force to continue.
Aborted due to warnings.
If I use the --force
flag then it compiles with warnings, but trying out the interactive code in psci
fails with a similar error.
Are there some deps missing from one of Gruntfile.js
/package.json
/bower.son
?
Or maybe the purescript-lists
dep in bower.json
should be pinned to a version range with ~
?
The diagonal example should be:
module Main where
import Math (sqrt)
import Control.Monad.Eff.Console (logShow)
import Prelude
diagonal w h = sqrt (w * w + h * h)
main = logShow (diagonal 3.0 4.0)
I found first import of logShow
in Chapter 7
When running the code on psc 0.10.1 the output is actually 5.0
not 5
as described in the book.
I wonder if it's correct to put this here.
I cannot get a correct solution of exercise 3 of Chapter 4.15.
(with psc version 0.5.5)
The exercise is
- (Medium) Rewrite the following function in tail recursive form using an accumulator parameter:
count :: forall a. (a -> Boolean) -> [a] -> Number count _ [] = 0 count p (x : xs) = if p x then 1 + count p xs else count p xs
My answer in PS is
count :: forall a. (a -> Boolean) -> [a] -> Number
count = count' 0
where
count' c p [] = c
count' c p (x:xs) = count' (if p x then (1 + c) else c) p xs
The output Javascript is optimized with while
loop and I think it is in tail recursive form:
var count = (function () {
var count$prime = function (__copy__233) {
return function (__copy__234) {
return function (__copy__235) {
var _233 = __copy__233;
var _234 = __copy__234;
var _235 = __copy__235;
tco: while (true) {
if (_235.length === 0) {
return _233;
};
if (_235.length >= 1) {
var _269 = _235.slice(1);
var __tco__233 = _234(_235[0]) ? 1 + _233 : _233;
var __tco__234 = _234;
_233 = __tco__233;
_234 = __tco__234;
_235 = _269;
continue tco;
};
throw new Error("Failed pattern match");
};
};
};
};
return count$prime(0);
})();
But when I test with the following code in psci
, I got an error RangeError: Maximum call stack size exceeded
.
> count (flip (>) 0) (-10000..10)
If I put the generated JavaScript code in Chrome console, and test is with following code, I got the correct answer.
var range = function(a, b){
var arr = [];
for ( var i = a ; i <= b; i++){
arr.push(i);
}
return arr;
}
count( function(x){return x > 0})(range(-10000,10));
This book is an excellent introduction for beginners, which I happily recommend to anyone who wants to learn PureScript/Haskell. However the installation section still suggests building PureScript from Source. Now that PureScript is npm installable I think you could severely lower the entry bar by suggesting a npm install -g purescript
.
To allow people who are jumping around to have it "just work". For instance, I went directly to chapter 8 since I wanted to learn how to wrap an external javascript library.
I cloned this repo, opened the chapter 8 directory, and:
~/s/purescript-book/chapter8:master* λ bower update
~/s/purescript-book/chapter8:master* λ pulp browserify --to dist/Main.js
* Browserifying project in /home/cody/source/purescript-book/chapter8
* Building project in /home/cody/source/purescript-book/chapter8
* Build successful.
* Browserifying...
events.js:160
throw er; // Unhandled 'error' event
^
Error: Cannot find module 'react-dom' from '/home/cody/source/purescript-book/chapter8/output/ReactDOM'
at /home/cody/.npm-packages/lib/node_modules/pulp/node_modules/resolve/lib/async.js:46:17
at process (/home/cody/.npm-packages/lib/node_modules/pulp/node_modules/resolve/lib/async.js:173:43)
at ondir (/home/cody/.npm-packages/lib/node_modules/pulp/node_modules/resolve/lib/async.js:188:17)
at load (/home/cody/.npm-packages/lib/node_modules/pulp/node_modules/resolve/lib/async.js:69:43)
at onex (/home/cody/.npm-packages/lib/node_modules/pulp/node_modules/resolve/lib/async.js:92:31)
at /home/cody/.npm-packages/lib/node_modules/pulp/node_modules/resolve/lib/async.js:22:47
at FSReqWrap.oncomplete (fs.js:123:15)
It would have saved me about 20 minutes if I'd seen:
For those jumping chapter to chapter, before building you'll need to npm install react react-dom
.
I actually only got my answer after googling that error and finding some irc history.
Thoughts?
It doesn't compile unless the exercises from chapter 7 were completed in a very specific manner leaving the Person
type unchanged, an unchanged validatePerson
function renamed to validatePerson'
and examplePerson
unchanged.
Even once these errors have been fixed it does not compile.
Running "psc:all" (psc) task
>> Error creating file dist/Main.js
>>
Warning: Error in module Data.AddressBook.UI:
Error in value declaration validateControls:
Error checking that type
Control.Monad.Eff.Eff (trace :: Debug.Trace.Trace | u9785) u9782
subsumes type
Control.Monad.Eff.Eff (dom :: Control.Monad.Eff.DOM.DOM, trace :: Debug.Trace.Trace | eff9780) (Data.Either.Either [Prim.String] Data.AddressBook.Person)
Error at src/Data/AddressBook/UI.purs line 50, column 1 - line 64, column 1:
Cannot unify type
Data.Validation.V
with type
Data.Either.Either
See https://github.com/purescript/purescript/wiki/Error-Code-ErrorUnifyingTypes for more information, or to contribute content related to this error. Use --force to continue.
I imagine this is because there is some validatePerson'
which hasn't been committed.
In, for example, chapter 3, the text of the book tells me to run pulp dep update
and then pulp build
. Running pulp dep update
gives me a warning that it's deprecated and to use Bower instead. After the warning, it installs some things and then says:
Unable to find a suitable version for purescript-foldable-traversable, please choose one:
1) purescript-foldable-traversable#~0.2.1 which resolved to 0.2.1 and is required by purescript-identity#0.2.0, purescript-lazy#0.2.0, purescript-lists#0.5.0
2) purescript-foldable-traversable#^0.4.0 which resolved to 0.4.2 and is required by purescript-tuples#0.4.0
Prefix the choice with ! to persist it to bower.json
? Answer
In the README, there are different instructions. I'm supposed to run npm install
, bower update
, and grunt
. Bower gives me the same messages about dependency conflicts. In addition, running grunt
gives this message:
$ grunt
Running "psc:all" (psc) task
>> Error creating file dist/Main.js
>>
Warning: Invalid option `--module=Data.PhoneBook'
Usage: psc [FILE] [-f|--ffi ARG] [-o|--output ARG] [--no-tco] [--no-magic-do]
[--no-opts] [-v|--verbose-errors] [-c|--comments]
[-r|--require-path ARG] [--source-maps] [-p|--no-prefix]
[--json-errors] Use --force to continue.
Aborted due to warnings.
There are more problems with the other examples.
On the plus side, the actual text of the book is very good.
Versions:
$ npm -v
2.14.12
$ grunt --version
grunt-cli v0.1.13
grunt v0.4.5
$ bower --version
1.7.7
$ pulp --version
Pulp version 8.0.0
psc version 0.8.2.0 using /usr/bin/psc
$ psc --version
0.8.2.0
$ node --version
v4.3.2
The example fundep is stream -> element
but in the next paragraph it refers to it by list -> element
.
class Stream stream element | stream -> element where uncons :: stream -> Maybe { head :: element, tail :: stream }Here,
list -> element
is called a functional dependency.
Since Int
is not a Monoid
for the repeatAction instance to work the class should be:
class Monoid m <= Action a m where
act :: a -> m -> m
git pull
on paf31/purescript-book
in Chapter3
npm install
bower update
Result:
bower purescript-lists#~0.3.3 not-cached git://github.com/paf31/purescript-lists.git#~0.3.3
bower purescript-lists#~0.3.3 resolve git://github.com/paf31/purescript-lists.git#~0.3.3
bower purescript-lists#~0.3.3 download https://github.com/paf31/purescript-lists/archive/v0.3.6.tar.gz
bower purescript-lists#~0.3.3 extract archive.tar.gz
bower purescript-lists#~0.3.3 EMALFORMED Failed to read /tmp/donnut/bower/purescript-lists-20044-bwQky7/bower.json
Ported from the old book-sources
repo:
Make sure you have npm installed and available on your path.
some might not know what a path is all about. Maybe telling them to check the version $ npm --v
or maybe the path itself but not sure this works on all OS's $ which npm
module Main where...
at the top?
import Math (sqrt)
potentially quickly explaining you can bring in multiple specific operators in the parentheses ie:
import Math (sqrt, pow, min)
or the whole lot if left out.
Project Goals:
Worth mentioning where to find the repo with example again? It was last mentioned in chapter 1 so might not be obvious anymore.
which is provided by the
purescript-lists
package which can be installed using Bower
I know it's mentioned in previous chapters but iterating how to use Bower might be helpful to those who have zero clue? bower i --save purescript-lists
just like ill-typed values result in type errors, ill-kinded types result in kind errors
Is it worth showing what would not throw a kind error, given previous failing example?
To enter a multi-line declaration in PSCi, we can use multi-line mode, by starting PSCi with the -m (or --multi-line-mode) option.
think I remember there being a new method of switching modes when in PSCi?
> flip (\n s -> show n <> s) "Ten" 10
\
anonymous functions haven't been explained yet
In PureScript, string concatenation uses the diamond operator (<>), instead of the plus operator like in Javascript.
I first read the example code and was confused by the (<>) spent a bit of time trying to work it out and not reading further, then noticing it's explanation was bellow! is it worth putting the explanation after first code example?
we can use the Cons function from Data.List...
I was left confused by what the Cons
does maybe giving a little example of it in action might help cons 1 [2, 3, 4] = [1, 2, 3, 4]
I already knew currying but this section left me a bit confused, I wasn't able to see how Currying worked with the address book, is it worth showing a simpler examples first like bellow or there are prob better examples out there 😄 :
add :: Int -> Int -> Int
add = /a -> /b -> a + b
increment :: Int -> Int
increment = add 1
-- calling `add 1` with one value returns a function awaiting another value
-- at this point add looks like: (maybe explain lazy evaluation)
-- add = /1 -> /b -> 1 + b
-- now calling increment with a value
-- increment 2 = 3
-- ad will look like this with the second value called:
-- add = /1 -> /2 -> 1 + 2
addFive :: Int -> Int
addFive = add 5
-- addFive 10 = 15
1.1 recursion helps to reduce the mutable state in our programs
Maybe a quick explanation of mutable state because if you are coming from OOP this might be an entirely new concept.
1.2
fact :: Int -> Int
fact 0 = 1
fact n = n * fact (n - 1)
Potentially break it down a little more to show what is actually happening when the function is recursing. Think this will be a new concept to those not used FP before, maybe something like this:
fact :: Int -> Int
fact 0 = 1
fact n = n * fact (n - 1)
-- every time a new _n_ comes into the function 1 is taken away from _n_ and the function is run again until _n_ hits 0 then the recursion stops.
fact 5 = 120
-- (fact 5 * (fact 4 * (fact 3 * (fact 2 *(fact 1 *(fact 1 ))))))
-- (5 * (4 * (3 * (2 * (1 * (1 ))))))
-- 5 * 4 * 3 * 2 * 1 * 1 = 120
else 1 + length (unsafePartial tail arr)
unsafePartial
hasn't been explain at this point, I personally don't quite understand it or partial
. it comes up again in chapter 6 but I still struggling with why they are used and what each do.
Unsure if this needs to be explained now or later.
infix 8 range as ..
I wasn't sure what 8 was in terms of the higher the number the more it overrides or is it the lower the number? in fact I've forgotten 😂
4.1 In the case of arrays, pure simply constructs a singleton array. In fact, we could modify our factors function to use this form, instead of using pure
the pure function threw me a little, so much like Maybe
it sort of becomes a wrapper / or imbeds it's results into an Array? Guess a little more clarity as to why it is useful and another good user case for it. When i read pure, I thought that somehow what I'd created was un-pured and needed purifying!
4.2 cartesian product of two arrays
A link or something to a cartesian product, as my non mathematical background I was left stumped 😄
In all honesty I was unable to figure out the exercises without finding some solutions elsewhere, they seemed very mathematically based and you needed to understand the naming to know what it should do or expected output. I also had to just look at JS examples to get what the output should look like.
> foldl (+) 0 (1 .. 5)
unsure if fold needs an example much like in recursion fact
or even pointing out that it works like JS reduce
? It might not be supper clear how it works inside. It is a little more with the show
example. Kind of difficult to show a foldl, maybe:
foldl (\acc n -> acc + n) 0 [1,2,3,4,5] -- 0 being the starting accumulator
foldl (\0 1-> 0 + 1) 0 [2,3,4,5]
foldl (\1 2-> 1 + 2) 0 [3,4,5]
foldl (\3 3-> 3 + 3) 0 [4,5]
foldl (\6 4-> 6 + 4) 0 [5]
foldl (\10 5-> 10 + 5) 0 []
-- array is empty no more recursion 10 + 5 = 15
reverse xs = snoc (reverse (unsafePartial tail xs))
what is snoc
? maybe getting reader to check out pursuit or quick explanation
6.1 the reverse example can be written as a fold
maybe another explanation of the inner workings?
reverse :: forall a. Array a -> Array a
reverse = foldr (\x xs -> xs <> [x]) []
reverse [1, 2, 3]
reverse = foldr (\3 [] -> [] <> [3]) [] -- [1, 2]
reverse = foldr (\2 [3] -> [3] <> [2]) [] -- [1]
reverse = foldr (\1 [3, 2] -> [3, 2] <> [1]) [] -- []
-- empty array return what is left [3, 2] <> [1]
[3, 2, 1]
Exercises
I worked through these at the meetup with you and I struggled a fair bit, not sure if they need more hints or a something to get them started then the reader fills in the holes?
(Medium) Look up Pascal’s Rule for computing binomial coefficients. Use it to write a function which computes binomial coefficients using pattern matching.
was really difficult to find a non mathematical representation of what this meant and made it really hard to understand the exercise.
sortPair :: Array Int -> Array Int
sortPair arr'@[x, y]
| x <= y = arr'
| otherwise = [y, x]
sortPair arr = arr
Would be really good to see a before and after example as it left me puzzled as to how the @
was bing used and the last sortPair
case also used arr
sortPair :: Array Int -> Array Int
sortPair [x, y]
| x <= y = [x, y]
| otherwise = [y, x]
sortPair arr = arr
-- above can be converted to use the named pattern
sortPair :: Array Int -> Array Int
sortPair arr'@[x, y]
| x <= y = arr'
| otherwise = [y, x]
sortPair arr = arr
2.1 (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
Not sure I understood the question properly and did the bellow code, not even sure that is right.
fromSingleton :: forall a. a -> Array a -> a
fromSingleton _ [x] = x
fromSingleton x _ = x
Here is an example. This function computes "longest zero suffix" of an array (the longest suffix which sums to zero)
took me a little while to understand that what sat between case <here> of
was in fact what was being evaluated on each recursion. So in this example:
lzs [1, -1, -2, 3]
-- first iteration
case sum xs of -- sum xs = 1
0 -> xs
_ -> lzs (tail xs) -- tail xs = [-1, -2, 3]
-- Second iteration
case sum xs of -- sum xs = 0
0 -> xs -- xs = [-1, -2, 3]
_ -> lzs (tail xs)
import Partial.Unsafe (unsafePartial)
partialFunction :: Boolean -> Boolean
partialFunction = unsafePartial \true -> true
When I saw the code I didn't have a clue what unsafePartial
was is it worth showing a compile error first then an runtime error with the explanation of unsafePartial
?
The constructors of an algebraic data type might have the same name as the ADT itself. This is quite common, and it is important not to confuse the
Point
type constructor with thePoint
data constructor - they live in different namespaces.
is this referring to data Point = Point
? I was left a little confused with different namespaces
and uses an infix operator alias
\/
to compute the union of the two bounding rectangles.
I ended up trying to find that \/
infix operator on pursuit here but I don't think this is the right operator for it's use here.
Hi,
I had some troubles getting over the exercise until someone at the #purescript/freenode guided me to Data.Array.Unsafe. Could it be added it the exercise? I also noticed a small typo (head x) vs. (head xs), also fixed below.
module Ex4 where
import Prelude
import Data.Array.Unsafe -- Add import clause
count :: forall a. (a -> Boolean) -> Array a -> Int
count _ [] = 0
count p xs = if p (head xs) -- Fix typo: (head x) ==> (head xs)
then count p (tail xs) + 1
else count p (tail xs)
Thanks for making browser development bearable again! :)
> firstName { firstName: "Phil", lastName: "Freeman", location: "Los Angeles" }
should be:
> fullName { firstName: "Phil", lastName: "Freeman", location: "Los Angeles" }
In $3.2, purescript-lists
is listed as a new dependency to install via bower
, but not purescript-control
.
The :i
command in psci
was replaced by import
, but is still referenced throughout.
In the example included in section 6.11, the hash
function of the Hashable
instance for String
calls charCodeAt
as though it will return a Number
instead of a Maybe Number
. The worked example in this repo does compile. The modification I came up with is kind of ugly but works without turning the string into an array first:
instance hashableString :: Hashable String where
hash s = go 0 0
where
go :: Number -> HashCode -> HashCode
go i acc = case (charCodeAt i s) of
Nothing -> acc
(Just n) -> (go (i + 1) acc) <#> n
In chapter 4.14 the exercise asks to rewrite:
import Prelude
import Data.Array.Unsafe (head, tail)
count :: forall a. (a -> Boolean) -> Array a -> Int
count _ [] = 0
count p xs = if p (unsafePartial head xs)
then count p (unsafePartial tail xs) + 1
else count p (unsafePartial tail xs)
using a fold. However, I can't figure out what the corresponding bower import for Data.Array.Unsafe should be.
show (Left 10 :: Either Number String)
should read
show (Left 10 :: Either Int 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.