Great content and lectures by Graham! I was able to follow all the previous lessons, meaning understanding almost all of them, until this one. It is hard to digest all the slides in the first a couple of runs. It would be a much better lecture if when you define a function, give one concrete example showing how it works. For example, in the slides that defines "values" and "solution", just giving some concrete sample data as input and output, instead of plainly describing the function definition and we should be all set. The reason for this is that such concepts which are so normal and easy in your mind, could be very difficult for us (normal programmers) to understand and digest.
This lecture is indeed more challenging that the previous ones. It's included as a more significant example of what can be done with Haskell, and brings together all the concepts that have been covered so far. Many thanks for the suggestion about including more examples.
Thank you again for the amazing content, it was cool to see a more sophisticated Haskell program in action. One comment, I think the perms and choices functions in the code you provided in another comment: perms :: [a] -> [[a]] perms [] = [[]] perms (x:xs) = concat (map (interleave x) (perms xs)) choices :: [a] -> [[a]] choices = concat . map perms . subs can be simplified to: perms :: [a] -> [[a]] perms = foldr (concatMap . interleave) [[]] choices :: [a] -> [[a]] choices = concatMap perms . subs
The function eval ensures that evaluation returns a positive natural number, so we need to check this in the base case, which is handled by the n > 0 check, and the recursive case, which is handled by the use of the valid function.
Using lists here allows the list comprehension machinery to be used to define the 'eval' function that evaluates expressions in a particularly nice way. We could use Maybe instead, but if we wanted a clean definition for 'eval' we'd need to use the monadic 'do' notation for Maybe, which goes beyond this intro course. The monadic behaviour of Maybe is covered in the advanced course.
Great content and lectures by Graham! I was able to follow all the previous lessons, meaning understanding almost all of them, until this one. It is hard to digest all the slides in the first a couple of runs. It would be a much better lecture if when you define a function, give one concrete example showing how it works. For example, in the slides that defines "values" and "solution", just giving some concrete sample data as input and output, instead of plainly describing the function definition and we should be all set. The reason for this is that such concepts which are so normal and easy in your mind, could be very difficult for us (normal programmers) to understand and digest.
This lecture is indeed more challenging that the previous ones. It's included as a more significant example of what can be done with Haskell, and brings together all the concepts that have been covered so far. Many thanks for the suggestion about including more examples.
Thank you again for the amazing content, it was cool to see a more sophisticated Haskell program in action.
One comment, I think the perms and choices functions in the code you provided in another comment:
perms :: [a] -> [[a]]
perms [] = [[]]
perms (x:xs) = concat (map (interleave x) (perms xs))
choices :: [a] -> [[a]]
choices = concat . map perms . subs
can be simplified to:
perms :: [a] -> [[a]]
perms = foldr (concatMap . interleave) [[]]
choices :: [a] -> [[a]]
choices = concatMap perms . subs
Are those operators you defined what would be known as an abstract syntax tree?
The Expr type is an example of an abstract syntax tree.
@@haskellhuttI see. ASTs are usually used for parsing right? Does it serve the same purpose as what people call "domain modeling"?
Why is eval (Val n) = [n| n > 0] and not just [n]? I think this might be redundant given that valid already disallows negative numbers no?
The function eval ensures that evaluation returns a positive natural number, so we need to check this in the base case, which is handled by the n > 0 check, and the recursive case, which is handled by the use of the valid function.
Instead of using a list, why not just use a maybe? Or a maybe nonemptylist?
Using lists here allows the list comprehension machinery to be used to define the 'eval' function that evaluates expressions in a particularly nice way. We could use Maybe instead, but if we wanted a clean definition for 'eval' we'd need to use the monadic 'do' notation for Maybe, which goes beyond this intro course. The monadic behaviour of Maybe is covered in the advanced course.
Here's the code from the video: www.cs.nott.ac.uk/~pszgmh/pgp-countdown.hs