Mercurial > repos > other > SevenLanguagesInSevenWeeks
comparison 7-Haskell/README.txt @ 87:2b5341fc4555
Add Haskell Day 1 code and notes
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Sat, 15 Jun 2019 17:31:22 +0100 |
parents | |
children | 7e4afb129bef |
comparison
equal
deleted
inserted
replaced
86:ab08b4bcd4a9 | 87:2b5341fc4555 |
---|---|
1 Install with `zypper install ghc` for the Glasgow Haskell Compiler. The interactive shell (REPL) is `ghci`. Currently on v8.6.5 (was 6.12.1 in the book). Haskell uses strong static types with inference. | |
2 | |
3 Numbers behave like numbers. Strings have double-quotes and characters have single quotes. An array of characters (in square brackets) is a string. "+" is purely numeric addition - concatenation is "++". | |
4 | |
5 Equality is tested with "==" (equals) and "/=" (not equals - not "is divisible by"!). Haskell is strongly typed | |
6 | |
7 Indentation is significant in Haskell (like Python) BUT you can do an "if … then … else …" on a single line (however, it will assume that "if then" is a parse error, probably because functional code isn't imperative and so can't miss the else) | |
8 | |
9 Using functions on the wrong type of arguments seems to give helpful error messages along the lines of "No instance for (arg types) arising from a use of 'function' at X" (and "+" is a function). | |
10 ":t val" lets you see the type of a variable or value, and ":set +t" lets you see the type of returned values. | |
11 | |
12 In code, functions are defined as "type function_name param = body". In code, that is always prefixed with "let". | |
13 Functions return the result of their last instruction. | |
14 Full function definitions are preceded by a type definition line in the form "function_name :: type(s) -> type(s)". You can also have generics and have "function_name :: (Parent_class generic_name) => generic_name -> generic_name". | |
15 Code in files needs to be in a module, which starts "module ModuleName where" on the top line. | |
16 You can then do `:load filename.hs` in the console. This then puts you in that module on the CLI (the prompt changes). | |
17 | |
18 Haskell functions can use parameter matching on arguments - see factorial.hs. | |
19 | |
20 Invoking parameters doesn't use brackets (because they're used for tuples - except when it's just a single value, when they're ignored). | |
21 | |
22 Lists can be broken up with "head" and "tail" functions (or "fst" and "snd" for tuples) *or* they can be broken up on assignment. It's like Python multi-assignment, but with colon - "(_head:_tail)" (":" is the list construction operator). It can then be used in function definitions, e.g.: | |
23 size [] = 0 | |
24 size (h:t) = 1 + size t | |
25 | |
26 Haskell can create ranges with [start..end]. Specifying an invalid range (e.g. decreasing) gives an empty list. Specifying an increment is different to all other languages: [start, next..end] (e.g. "[10, 8..4]" gives "[10, 8, 6, 4]" and it works out to decrement by 2). | |
27 You can also do (lazy) infinite ranges by not specifying an end and then using "take" functions etc to pull just the values you need. | |
28 | |
29 List comprehension is slightly pythonic: "[expr | val <- [vals] ]" where "expr" is the expression to calculate in the new list, val is a variable used in expr and [vals] is the source list. It's effectively "expression for value in list". | |
30 You can also assign multiple independent variables, possibly from the same source. For example: | |
31 let crew = ["Kirk", "Spock", "McCoy"] | |
32 [(a,b) | a <- crew, b <- crew] | |
33 calculates all combinations of crew names. Changing it to: | |
34 [(a,b) | a <- crew, b <- crew, a /= b] | |
35 lets you add filtering to stop people being paired with themselves. Or you could use "a < b" to make it return unordered unique pairings. |