You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The Haskell language is very self contained due to its pure nature.
5
+
Consecutive calls to a function with the same input *has* to produce the same result.
6
+
This does not allow for interactions with the stateful environment, like accessing the hard disk, network or database.
7
+
8
+
To separate these stateful actions from the pure Haskell has a type called ``IO``.
9
+
The ``IO`` type is used to tag functions and values.
10
+
For instance ``IO Int`` means that we can obtain an ``Int`` from this value if we let it execute some interaction with the environment.
11
+
12
+
A very common type is ``IO ()`` this means the function does I/O and then returns the ``()`` (unit) value.
13
+
This value contains no information (similar to ``null``) and ``IO ()`` is basically equivalent to ``void``.
14
+
It marks a function which we only want for its *effect*, not its returned *value*.
15
+
16
+
An nice example of this is the ``getLine`` function.
17
+
As you may imagine it reads a single line from stdin and gives us back what was entered.
18
+
Its type ``IO String`` then means that it returns a string after doing some interactions with the environment, in this case reading from the ``stdin`` handle.
19
+
20
+
``do`` ing IO
21
+
-------------
22
+
23
+
IO actions can be chained using the ``do`` syntax.
24
+
``do`` syntax is basically what every function body in an imperative language is, a series of statemens and assignments.
25
+
One important thing to note is that all statements in a ``do`` block are executed in sequence.
26
+
27
+
::
28
+
29
+
main = do
30
+
putStrLn "Starting work"
31
+
writeFile "Output" "work work work"
32
+
putStrLn "Finished work"
33
+
34
+
As you can see we can use ``do`` to execute several ``IO`` actions in sequence.
35
+
We can also obtain the values in from inside those tagged with ``IO``.
36
+
37
+
::
38
+
39
+
main = do
40
+
l <- getLine
41
+
putStrLn ("You entered the line: " ++ l)
42
+
43
+
The ``binding <- ioExpr`` syntax means "execute the I/O from ``ioExpr`` and bind the result to ``binding``".
44
+
Since ``<-`` is only for ``IO`` tagged values you cannot use it for pure ones.
45
+
To handle pure values use the statement for of ``let``: ``let binding = expr`` (notice no ``in``).
46
+
47
+
::
48
+
49
+
action :: IO ()
50
+
actions = do
51
+
l <- getLine
52
+
let computed = computeStruff l
53
+
return computed
54
+
55
+
The ``do`` syntax does however not actualy execute the ``IO``.
56
+
It merely combines several ``IO`` actions into a larger ``IO`` action.
57
+
The value from the last statement in a ``do`` block is what the whole thing returns.
58
+
For instance if the last statement was `putStrLn "some string"` the type of the whole block would be ``IO ()`` (void).
59
+
If it was ``getLine`` the type would be ``IO String``.
60
+
You can also return non-I/O values from within ``do`` by tagging them with ``IO`` using the ``return`` funciton.
61
+
62
+
63
+
64
+
Running ``IO``
65
+
--------------
66
+
67
+
To execute the action there are two ways.
68
+
69
+
#. GHCi
70
+
If you type an ``IO`` action into ghci it will execute it for you and print the returned value.
71
+
72
+
#. The ``main`` function.
73
+
74
+
When you compile and run a Haskell program or interactively run a Haskell source file the compiler will search for a ``main`` function of type ``IO ()`` and execute all the I/O inside it.
75
+
This means you must tie all the I/O you want to do somehow back to the main function.
76
+
This is similar to a C program for instance where the ``int main()`` function is the only one automatically executed and all other routines have to be called from within it.
77
+
78
+
``do`` Overload
79
+
---------------
80
+
81
+
There are more container and tag types which can be used similar to ``IO``.
82
+
To be more precise they can be used with the ``do`` notation, just like ``IO`` can.
83
+
84
+
Examples of such structures are ``[a]``, ``Maybe a``, ``State s a`` and ``Reader e a``.
85
+
Like ``IO`` all these structures represent some kind of context for the contained value ``a``.
86
+
87
+
We will explore this in more detail later.
88
+
89
+
For now it suffices that in Haskell these structures are generalized with a typeclass called ``Monad``.
90
+
The ``Monad m`` typeclass requires two capabilities: ``return :: a -> m a`` to wrap a value ``a`` into the monad ``m`` and bind ``(>>=) :: m a -> (a -> m b) -> m b`` which basically states that the computations with context (the *Monad*) can be chained.
91
+
92
+
This is all that is necessary to enable them to use the ``do`` notation.
93
+
94
+
There is a nice library called `monad-loops`_ which implements many of the control structures one is used to from imperative languages in terms of ``Monad``.
<h1>8.5. Simple I/O<aclass="headerlink" href="#simple-i-o" title="Permalink to this headline">¶</a></h1>
47
+
<divclass="section" id="reverser">
48
+
<h2>8.5.1. Reverser<aclass="headerlink" href="#reverser" title="Permalink to this headline">¶</a></h2>
49
+
<p>Write an application which reads a line from stdin and prints the same string back, but reversed.</p>
50
+
<p>Modify it so it keeps repeating this process forever.</p>
51
+
</div>
52
+
<divclass="section" id="bulk-rename">
53
+
<h2>8.5.2. Bulk rename<aclass="headerlink" href="#bulk-rename" title="Permalink to this headline">¶</a></h2>
54
+
<p>You will need the <aclass="reference external" href="https://www.stackage.org/lts-8.13/package/filepath-1.4.1.1">filepath</a> and <aclass="reference external" href="https://www.stackage.org/lts-8.13/package/directory-1.3.0.">directory</a> library.</p>
55
+
<p>Implement a function which:</p>
56
+
<ulclass="simple">
57
+
<li>takes as argument a string</li>
58
+
<li>then scans the current directory and finds all files</li>
59
+
<li>renames each file by prepending the string argument to the filename</li>
60
+
</ul>
61
+
<divclass="section" id="advanced">
62
+
<h3>8.5.2.1. Advanced<aclass="headerlink" href="#advanced" title="Permalink to this headline">¶</a></h3>
63
+
<p>Get the input string from the application arguments <aclass="footnote-reference" href="#getargs" id="id1">[1]</a>.</p>
64
+
</div>
65
+
</div>
66
+
<divclass="section" id="combine-files">
67
+
<h2>8.5.3. Combine files<aclass="headerlink" href="#combine-files" title="Permalink to this headline">¶</a></h2>
68
+
<p>You will need the <aclass="reference external" href="https://www.stackage.org/lts-8.13/package/filepath-1.4.1.1">filepath</a> and <aclass="reference external" href="https://www.stackage.org/lts-8.13/package/directory-1.3.0.">directory</a> library.</p>
69
+
<p>Implement a function which:</p>
70
+
<ulclass="simple">
71
+
<li>Scans the current directory</li>
72
+
<li>finds all files</li>
73
+
<li>reads each file and collects the contents in a list</li>
74
+
<li>writes a combined output file with the contents of each of the files concatenated.</li>
75
+
</ul>
76
+
<divclass="section" id="id2">
77
+
<h3>8.5.3.1. Advanced<aclass="headerlink" href="#id2" title="Permalink to this headline">¶</a></h3>
78
+
<p>Instead of collecting to a list open the output file first and write each files contents to the output handle right away.</p>
0 commit comments