Added explanation of guess number
This commit is contained in:
parent
ec443f0b85
commit
7f58cb3285
2 changed files with 83 additions and 3 deletions
|
@ -550,10 +550,50 @@ guessNum nbTry nbToFound = do
|
||||||
guessNum (nbTry + 1) nbToFound
|
guessNum (nbTry + 1) nbToFound
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
#+BEGIN_COMMENT
|
Let's read the program line by line:
|
||||||
****** TODO Let's explain each line of the that function.
|
|
||||||
#+END_COMMENT
|
|
||||||
|
|
||||||
|
- ~putText "What is your guess?"~ should be straightforward.
|
||||||
|
- ~answer <- getLine~ So the ~getLine~ read from standard input and returns the
|
||||||
|
line entered by the user. The line will be put in the ~answer~ variable.
|
||||||
|
- ~let guessedNumber = readMaybe (toS answer)~: there are a few things to tell about this line.
|
||||||
|
|
||||||
|
If you open GHCI and ask the type for each interresting symbol here is what you get:
|
||||||
|
|
||||||
|
#+BEGIN_SRC
|
||||||
|
λ :t getLine
|
||||||
|
getLine :: IO Text
|
||||||
|
|
||||||
|
λ :t toS
|
||||||
|
toS :: StringConv a b => a -> b
|
||||||
|
|
||||||
|
λ :t readMaybe
|
||||||
|
readMaybe :: Read a => GHC.Base.String -> Maybe a
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
- ~answer~ comes from ~getLine :: IO Text~ so ~answer~ should have the type ~Text~.
|
||||||
|
- Now we want to read this ~Text~ and see if this is a number and compare it to another ~Int~.
|
||||||
|
- To transform the number we don't use a function ~textToInt~ we simply use a
|
||||||
|
quite generic function ~readMaybe~ that take some ~String~ and try to
|
||||||
|
transform that to some type. For our specific case, the compiler is able to
|
||||||
|
figure out the type we want to transform the text into is ~Int~. Take the
|
||||||
|
time to digest that: ~Int~ is specified in the type signature of the
|
||||||
|
~guessNum~ function so the compiler could discover that ~readMaybe~ should
|
||||||
|
return a ~Maybe Int~. How does he do that? Let's follow:
|
||||||
|
1. see a ~n == nbToFound~ so we can deduce ~n~ and ~nbToFound~ have the same type.
|
||||||
|
2. Reading the type signature of the function it is clear ~nbToFound~ is of
|
||||||
|
type ~Int~ (it's the second argument of a function with type ~Int -> Int -> IO ()~)
|
||||||
|
3. Then ~n~ is generated from a pattern matching; the case ~Just n~ which
|
||||||
|
could be the the result of the ~readMaybe~ function. So we can deduce
|
||||||
|
that the ~a~ in the type signature of ~readMaybe~ is ~Int~ for this specific case.
|
||||||
|
- so ~guessedNumber :: Maybe Int~, if the user enter something that cannot be
|
||||||
|
transformed in number from a string then ~guessedNumber~ would be equal
|
||||||
|
to ~Nothing~ and we ask the user to enter a number. If the user entered a
|
||||||
|
number the type will be ~Just n~ were ~n~ will be an ~Int~.
|
||||||
|
- We compare the ~guessedNumber~ to the number to found ~nbToFound~.
|
||||||
|
- If the user found the right number we stop here by displaying the number of try.
|
||||||
|
- If the user hasn't found the number, depending on its value we tell the user
|
||||||
|
it's either too low or too high and we call the same function, this time, we
|
||||||
|
increment the number of try.
|
||||||
|
|
||||||
The full program is then:
|
The full program is then:
|
||||||
|
|
||||||
|
@ -718,6 +758,28 @@ to use a library to parse options.
|
||||||
|
|
||||||
For that we will use the =optparse-generic= package.
|
For that we will use the =optparse-generic= package.
|
||||||
|
|
||||||
|
|
||||||
|
#+BEGIN_SRC haskell :tangle code/optparse_1.hs
|
||||||
|
#!/usr/bin/env stack
|
||||||
|
{- stack script
|
||||||
|
--resolver lts-11.6
|
||||||
|
--install-ghc
|
||||||
|
--package protolude
|
||||||
|
--package optparse-generic
|
||||||
|
-}
|
||||||
|
{-# LANGUAGE NoImplicitPrelude #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
import Protolude
|
||||||
|
import System.Environment (getArgs)
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
arguments <- getArgs
|
||||||
|
case head arguments of
|
||||||
|
Just filename -> die ("The first argument is: " <> toS filename)
|
||||||
|
Nothing -> die "Please enter a filename"
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
*** TODO File Access
|
*** TODO File Access
|
||||||
*** TODO Daemons & Logging
|
*** TODO Daemons & Logging
|
||||||
** TODO Intermediate
|
** TODO Intermediate
|
||||||
|
|
18
code/optparse_1.hs
Executable file
18
code/optparse_1.hs
Executable file
|
@ -0,0 +1,18 @@
|
||||||
|
#!/usr/bin/env stack
|
||||||
|
{- stack script
|
||||||
|
--resolver lts-11.6
|
||||||
|
--install-ghc
|
||||||
|
--package protolude
|
||||||
|
--package optparse-generic
|
||||||
|
-}
|
||||||
|
{-# LANGUAGE NoImplicitPrelude #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
import Protolude
|
||||||
|
import System.Environment (getArgs)
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
arguments <- getArgs
|
||||||
|
case head arguments of
|
||||||
|
Just filename -> die ("The first argument is: " <> toS filename)
|
||||||
|
Nothing -> die "Please enter a filename"
|
Loading…
Reference in a new issue