Tutorial 2: Functions and types - init#2
Conversation
|
|
||
| ### Function declaration | ||
|
|
||
| Although type can be in most cases inferred automatically by the compiler, it is good practice to write it down at least in case of functions as part of code documentation. Functions can be complicated and by reading its type signature you know immediately what arguments it expects and what it returns. |
There was a problem hiding this comment.
... a good practice ...
... as a part of code ...
|
|
||
| myAge :: Age | ||
| myAge = Age 20 | ||
| ``` |
There was a problem hiding this comment.
Here, type String can be replaced by [Char] (it is a mere synonym), so typechecking is not 'perfect' in this sense. In case of newtype, Age is a different type than Int and compiler will check it.
| * `Enum` - for enumerations, allows the use of `..` range list syntax such as `[Blue .. Green]` | ||
| * `Bounded` - for enumerations or other bounded, `minBound` and `maxBound` as the lowest and highest values that the type can take | ||
|
|
||
| As it was said, typeclasses are very important in Haskell and will be covered later on. You will also learn how to make new typeclasses, their instances, etc. |
There was a problem hiding this comment.
... typeclasses are a very important means of abstraction in Haskell ...
|
|
||
| ## Data types | ||
|
|
||
| Haskell has a strong static type system which is one of the things making it so great. As we already saw, every expression in Haskell has some type and the type cannot change during runtime (that is the difference with dynamic typing). As in other programming languages can use predefined data types, get more from some libraries or introduce your own. |
| x = MyTypeC1 True 10 | ||
| ``` | ||
|
|
||
| Usually, when there is just one data constructor, the name is the same as of the type constructor (but it is not a rule). |
There was a problem hiding this comment.
This is one another great Haskell feature: Algebraic Data Types (ADT). These are now found in more and more new languages (e.g. 'Rust' and very fresh 'Reason' from Facebook)
| } deriving Show | ||
| ``` | ||
|
|
||
| Now try to create a type `Pet` which also contains `name` and `age`. You will get an error which is logical, you cannot have two functions with the same name! One option is to rename it to `namePerson` and `namePet`, the second is available to you only if you have GHC 8.0.1 or higher and it is with language extension [DuplicateRecordFields](https://downloads.haskell.org/~ghc/master/users-guide/glasgow_exts.html#duplicate-record-fields): |
There was a problem hiding this comment.
, however the first option is more common
| olderPet pet = pet { age = (age pet + 1) } | ||
| ``` | ||
|
|
||
| You can also see that there is a shorthand for updating the value of record - creating new edited record from previous. Now you can try some derived behaviour from typeclasses such as `show`, `read`, or `==`: |
There was a problem hiding this comment.
This is one of the weaker parts of Haskell: it actually does NOT have records (as explained, there is just a syntactic sugar upon tuples). Newer languages from the Haskell family PureScript and Elm elaborated on this and introduced 'proper' records.
| ("Hello",7) | ||
| ``` | ||
|
|
||
| Good to know is how it actually works and try to implement own tuples. |
| data List a = Empty | NonEmpty a (List a) | ||
| ``` | ||
|
|
||
| That's it! List of type `a` it either `Empty` or `NonEmpty` which means that it has an element and then rest of the list (which can be again `Empty` or `NonEmpty`). Sometimes the following naming is used: |
|
|
||
| ### String | ||
|
|
||
| String is really nothing but just list of characters `[Char]`. The only difference is that there are more functions for working especially with `String`s - like `putStr`, `lines`, `words` and more (see [Data.String]). For more efficient working with strings is [text] package providing "a time and space-efficient implementation of Unicode text" with [Data.Text] - two variants: Lazy and Strict. Later on, we will get back to this problem which makes a life of Haskell programmer sometimes little bit uneasy. |
|
|
||
| ## Simple functions | ||
|
|
||
| Enough of types and containers, let's do some functions when this is functional programming course! |
There was a problem hiding this comment.
a functional programming...
|
|
||
| ### Basic list functions | ||
|
|
||
| Since list is very simple and widely used data structure, it is a good time to learn useful functions to work with lists. You can find a complete list in [Data.List] documentation. Try following examples and examine the type of functions if needed. Also, try to run some unclear cases like `head` of the empty list and see what happens... |
There was a problem hiding this comment.
a very simple and widely used
| False | ||
| ``` | ||
|
|
||
| The last one is left fold, there is also right fold (depends on associativity), we will cover this in more detail later while explaining so-called catamorphism. Now you can just see that it is a generalization of `sum`, `and`, `or`, and many others. |
|
|
||
| The last one is left fold, there is also right fold (depends on associativity), we will cover this in more detail later while explaining so-called catamorphism. Now you can just see that it is a generalization of `sum`, `and`, `or`, and many others. | ||
|
|
||
| It is very good practice to try to implement some of these functions to understand them and their complexity. You may worry that using list is always very inefficient, luckily GHC can do some optimizations (although still in some cases you should prefer [Data.Sequence] or other [containers] - we will get back to this during the course). |
| factorial n = n * factorial n-1 | ||
| ``` | ||
|
|
||
| During any call of subroutine (function, procedure, or other action), it is needed to store information to the [call stack]. Such information consist of where was the call initiated, what was the state and where it should return the value when poping from this stack. For example, with calling `res = factorial 3` call stack could look like this (top on the left): |
Second tutorial initial version for this semester (B172) is ready, please review and add/change something if necessary...