Giter Club home page Giter Club logo

purescript-book's People

Contributors

fmancinelli avatar jw120 avatar minikomi avatar paf31 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

purescript-book's Issues

insertEntry example is wrong

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 !?

psci not executable after installed with bower!?

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?

Missing Data.List.Cons in 0.8.3

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?

Missing Gruntfile referenced in Chapter 8

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?

purescript 0.7 Number /= Int bugs in text

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.

Chapter 7 - f used to represent both function and functor in the same paragraph, sort of confusing

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.

forall never really explained

> :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 questions about current version

Some of the possible buggy things I observed. Just for your reference.

  1. In the "Conclusion" section of "Generative Test" Chapter, the first one mentioned Grunt like that "We saw how to automate QuickCheck tests using Grunt." But I can find anywhere mentioning Grunt more in this chapter.
  2. In the 12.7 section, par function is used but current purescript-parallel package don't have such interface anymore as I found. It might be misleading.
  3. Just at the beginning of 11.11 section, there is one line of type class definition class (Applicative f, Plus f) <= Alternative f where, which ends up with a strange where
  4. 11.9 section mentioned 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!

`pulp build --to dist/Main.js` failed but `pulp build --to Main.js` succeeded

In Chapter8:

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.

My platform:

  1. Operating System: Ubuntu 14.04.3
  2. PureScript: pre-compiled binary 0.7.2.0

Unable to build chapter 4

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

Chapter 7 Build Issue

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?

Typos and feedback

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

5.17

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?

6.8

Might be nice to introduce uncons or share the motivation--I'm guessing this is to avoid the unsafePartials 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

6.9

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.

Typos / small suggestions

  • 4.4 the dependency purescript-arrays is now needed to import Data.Array
  • 6.2 small typo in (the letter Â) after src/Data/Hashable.purs.
  • 6.9 I assume that _.head is equivalent to \x -> x.head, but would be nice to know
  • 6.11 Perhaps explicitly repeat class Eq a <= Ord a to clarify

3.2 - Some dependencies are missing

3.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"

Chapter 9 - Random example

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.

Errors while building Chapter 10

While building the code in Chapter 10 using grunt, I have errors regarding Data.Monoid.Additive module : "Unknown type Semiring" (line 48 and 51)

Unable to build Chapter3 code

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 ?

Strange code formatting in 6.11's exercises

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

Chapter 3 - Reverse example

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.

New dependencies not documented (control + lists)

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.

Chapter 3 fails to build

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 ~?

Chapter 3 - Diagonal example missing logShow import

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

2.10 output is 5.0 not 5

When running the code on psc 0.10.1 the output is actually 5.0 not 5 as described in the book.

Tail Recursion in PureScript

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

  1. (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));

Update installation instructions

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.

Chapter 8 should give full build instructions

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?

Check shapeBounds is consistent

@kilkelly reports in #47 that the shape bounds calculation might be inconsistent. I need to make sure that whichever way round it is (lower number at the top or vice versa) that it is consistent.

Chapter 8 doesn't compile

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.

Many (all?) of the examples won't build.

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

Typo in: 6.9 Functional Dependencies

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.

bower.json malformed?

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

Suggestions by @cmdv

Ported from the old book-sources repo:

Chapter 2

  1. Installing Tools:

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

  1. Computing Diagonals:
    does the file still need 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.

Chapter 3

  1. 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.

  2. Project setup:

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

  1. Type Constructors and Kinds:

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?

  1. Simple Types:

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?

  1. Quantified Types:

> flip (\n s -> show n <> s) "Ten" 10

\ anonymous functions haven't been explained yet

  1. Displaying Address Book Entries:

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?

  1. Creating Address Books:

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]

  1. Curried Functions:

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

Chapter 4

  1. Introduction:

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
  1. Recursion on Arrays:

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.

  1. Infix Operators:

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 😂

  1. Do Notation:

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.

  1. Folds:

> 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
  1. Accumulators:

reverse xs = snoc (reverse (unsafePartial tail xs))

what is snoc? maybe getting reader to check out pursuit or quick explanation

  1. Prefer Folds to Explicit Recursion:

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]
  1. Listing All Files:

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?

Chapter 5

  1. Simple Patterns:

(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.

  1. Named Patterns:
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 type forall 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
  1. Case Expressions:

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)
  1. Pattern Match Failures and Partial Functions:
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?

  1. Algebraic Data Types:

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 the Point data constructor - they live in different namespaces.

is this referring to data Point = Point ? I was left a little confused with different namespaces

  1. Computing Bounding Rectangles

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.

Fix for section 4.15, exercise 3

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! :)

Error in 8.11

> firstName { firstName: "Phil", lastName: "Freeman", location: "Los Angeles" }

should be:

> fullName { firstName: "Phil", lastName: "Freeman", location: "Los Angeles" }

Chapter 3 errata

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.

Example in section 6.11 doesn't unwrap `Just`

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

Chapter 5 - Data.Array.Unsafe dependency in 5.10

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.

Error in chapter 6.3

show (Left 10 :: Either Number String)

should read

show (Left 10 :: Either Int String)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.