Clearing
It is a small forest path.
data Location =
Home
| Friend'sYard
| Garden
| OtherRoom - Added new constructor.
deriving ( Eq )
* Main > Home / = Friend'sYard
True
* Main > Home == OtherRoom
False
< interactive > : 1 : 1 :
No instance for ( Show Location )
arising from a use of ' show '
Possible fix: add an instance declaration for ( Show Location )
In the expression: show Home
In this equation for 'it': it = show Home
data Location =
Home
| Friend'sYard
| Garden
| OtherRoom
deriving ( Eq , Show )
* Main > : r
[ 1 of 1 ] Compiling Main ( H: \ Haskell \ QuestTutorial \ Quest \ QuestMain . Hs , interpreted )
Ok , modules loaded: Main .
* Main > show Home
"Home"
* Main > "Current location name:" ++ show Home ++ "."
“Current location name: Home.”
* Main > show Friend'sYard
"Friend'sYard"
describeLocation :: Location -> String
describeLocation loc = case loc of
Home -> "You are standing in the middle of the wooden table."
Friend'sYard -> “You ’ve been behind a small wooden fence.”
Garden -> “You are in the garden. Garden looks very well: clean, tonsured, cool and wet. "
otherwise -> "No description available for location with name" ++ show loc ++ "."
* Main > describeLocation OtherRoom
“No description available for location with name OtherRoom.”
Type constructors, such as Home, Friend'sYard or Garden, are in fact special features that are allowed to begin with a capital letter. And since these are functions, they have a type. What will the ": type Home" command give? It's elementary, Watson.
* Main>: type Home
Home :: Location
describeLocation loc = case loc of
Home -> "Home \ " You are in the middle of the wooden table.
'S 's Y Friend Y>>>>>>>
Garden -> “Garden \ n You are in the garden. Garden looks very well: clean, tonsured, cool and wet. "
otherwise -> "No description available for location with name" ++ show loc ++ "."
describeLocation loc = case loc of
Home -> Show Loc ++ " \ n " ++ "You are standing at the wooden table."
'S behind « « «« «« «« «« «« «« «« «« «« «
Garden -> show loc ++ " \ n " ++ “You are in the garden. Garden looks very well: clean, tonsured, cool and wet. "
otherwise -> "No description available for location with name" ++ show loc ++ "."
describeLocation loc = show loc ++ " \ n " ++
case loc of
Home -> "You are standing in the middle of the wooden table."
Friend'sYard -> “You ’ve been behind a small wooden fence.”
Garden -> “You are in the garden. Garden looks very well: clean, tonsured, cool and wet. "
otherwise -> "No description available for location with name" ++ show loc ++ "."
* Main > describeLocation Home
"You are standing in the middle of the wooden table."
* Main > putStrLn ( describeLocation Home )
Home
You are standing in the middle of the wooden table .
The case design is definitely good. There are, however, cases when it is inconvenient. If you solved problem # 2 from the first part, you can already guess what I mean. I recall that there it was necessary to implement the following function for some x and a:
| ln (abs (sin (x))) if x> 5 y = | x ^ 2 + a ^ 2 if x <= 5 and a <= 3 | x / a + 7.8 * a, if x <= 5 and a> 3
Function as a function, in mathematics such darkness. But try implementing it in Haskell with an if-then-else or case:
y x a = if x > 5
then log ( abs ( sin ( x ) ) )
else
if x <= 5 && a <= 3
then x ^ 2 + a ^ 2
else x / a + 7.8 * a
y 'x a = case x > 5 of
True -> log ( abs ( sin ( x ) ) )
False -> case x <= 5 && a <= 3 of
True -> x ^ 2 + a ^ 2
False -> x / a + 7.8 * a
The function is difficult to read due to several levels of nesting. Can it not be otherwise? .. Well, of course! Security expressions! And the Haskell function becomes similar to the function in mathematics. See:
y '' x a | x > 5 = log ( abs ( sin ( x ) ) )
y '' x a | x <= 5 && a <= 3 = x ^ 2 + a ^ 2
y '' x a | otherwise = x / a + 7.8 * a
- Or the same:
y '' x a | x > 5 = log ( abs ( sin ( x ) ) )
| x <= 5 && a <= 3 = x ^ 2 + a ^ 2
| otherwise = x / a + 7.8 * a
It is easy to understand that the function takes the form "log (abs (sin (x)))" if x is greater than five. Guard expression (guard) is an expression between the characters "|" and "=". For security expressions, the same laws apply as for alternatives to the case-construction: the set of expressions must be complete, and otherwise it always works.
run =
do
x <- getLine
putStrLn x
* Main > run
Hello ! - What I introduced
Hello ! - What the putStrLn function printed
* Main > run
kjljfs
kjljfs
run = do
putStr "Enter command:"
x <- getLine
putStrLn x
* Main > run
Enter command: Look
Look
You, of course, noticed that I wrote "we connect with x", but not "we appropriate x". There is no assignment in Haskell, which is why the arrow ("<-") is there, and not the assignment mark ("=", ": ="). The arrow shows where we take the result and what we associate it with. There is a significant difference between assignment and binding with far-reaching consequences. But as long as we do not use these effects, then we should not worry.
evalAction :: String -> String
evalAction strAct = "Action:" ++ strAct ++ "!"
run = do
putStr "Enter command:"
x <- getLine
putStrLn ( evalAction x )
- We are testing:
* Main > run
Enter command: Look
“Action: Look!”
* Main > run
Enter command: Quit
“Action: Quit!”
* Main > run
Enter command: lubaya _ abrakadabra
“Action: lubaya_abrakadabra!”
evalAction :: Action -> String
evalAction act = "Action:" ++ show act ++ "!"
run = do
putStr "Enter command:"
x <- getLine
putStrLn ( evalAction x )
* Main > : r
[ 1 of 1 ] Compiling Main ( H: \ Haskell \ QuestTutorial \ Quest \ QuestMain . Hs , interpreted )
H: \ Haskell \ QuestTutorial \ Quest \ QuestMain . hs: 46 : 38 :
Couldn't match expected type 'Action' with actual type ' [ Char ] '
Expected type : Action
Actual type : String
In the first argument of 'evalAction' , namely 'x'
In the first argument of ' putStrLn ' , namely ' ( evalAction x ) '
Failed , modules loaded: none .
When programming in Haskell, you will often see typing errors. There is nothing wrong with that; it says in them where the discrepancy is, what was expected to receive (Expected type), and what they actually received (Actual type). It is impossible to compile the wrong code. With a large refactoring, up to several dozens of errors can occur, or even more, and you will have to fix them all, one, another, the third ... When the errors finally disappear, the code with a high probability will work exactly as you expect. And this, I tell you, is very, very cool!
convertStringToAction :: String -> Action
convertStringToAction :: String -> Action
convertStringToAction str = case str of
“Look” -> Look
"New" -> New
otherwise -> Quit
- We process the action.
evalAction :: Action -> String
evalAction act = "Action:" ++ show act ++ "!"
- Convert a string to Action
convertStringToAction :: String -> Action
convertStringToAction str = case str of
“Look” -> Look
"New" -> New
otherwise -> Quit
- We receive input from the keyboard, convert it into action, call the handler, display the result.
run = do
putStr "Enter command:"
x <- getLine
putStrLn ( evalAction ( convertStringToAction x ) )
* Main > : r
[ 1 of 1 ] Compiling Main ( H: \ Haskell \ QuestTutorial \ Quest \ QuestMain . Hs , interpreted )
Ok , modules loaded: Main .
* Main > run
Enter command: Look
Action: Look !
* Main > run
Enter command: dfdf
Action: Quit !
By the way, food for thought: two more ways to write the function convertStringToAction. Theses, without explanation.
- Security expressions (guards)
convertStringToAction ' :: String -> Action
convertStringToAction 'str | str == "Look" = Look
| str == "New" = New
| otherwise = Quit
- Pattern matching (pattern matching)
convertStringToAction '' :: String -> Action
convertStringToAction '' "Look" = Look
convertStringToAction '' "New" = New
convertStringToAction '' _ = Quit
- Check in ghci
* Main > convertStringToAction ' "New"
New
* Main > convertStringToAction '' "New"
New
data Location =
Home
...
deriving ( Eq , Show , Read )
data direction =
North
...
deriving ( Eq , Show , Read )
data Action =
Look
...
deriving ( Eq , Show , Read )
* Main > describeLocation Home
"You are standing in the middle of the wooden table."
* Main > describeLocation ( read "Home" )
"You are standing in the middle of the wooden table."
* Main > describeLocation ( read ( show Home ) )
"You are standing in the middle of the wooden table."
* Main > read "Home"
< interactive > : 1 : 1 :
Ambiguous type variable 'a0' in the constraint:
( Read a0 ) arising from a use of ' read '
Possible fix: add a type signature that fixes these type variable ( s )
In the expression: read "Home"
In an equation for 'it': it = read "Home"
* Main > read "Home" :: Location
Home
* Main > read "5.5" :: Float
5.5
* Main > read "True" :: Bool
- We process the action.
evalAction :: Action -> String
evalAction act = "Action:" ++ show act ++ "!"
- Convert a string to Action
convertStringToAction :: String -> Action
convertStringToAction str = read str
- We receive input from the keyboard, convert it into action, call the handler, display the result.
run = do
putStr "Enter command:"
x <- getLine
putStrLn ( evalAction ( convertStringToAction x ) )
- Check in ghci:
* Main > run
Enter command: Look
Action: Look !
* Main > run
Enter command: Quit
Action: Quit !
* Main > run
Enter command: abrakadabra
Action: *** Exception: Prelude . read : no parse
convertStringToAction :: String -> Action
convertStringToAction str = case reads str of
[ ( x , _ ) ] -> x
_ -> Quit
* Main > run
Enter command: abrakadabra
Action: Quit !
Tasks for fixing.
1. Objects of the quest and action Investigate.
- Make an “Object” ADT, add any objects there.
- Create a function describeObject, which gives a description of the object.
- Create an investigate function that queries the user for the name of the object and displays a description of this object.
2. The program "Dumb calculator."
There are integer operations "Add", "Subtract" and "Multiply".
Write a program that requires the user to integer1, then requires an integer operation, then requires an integer2. When this is all received, the program must perform the corresponding operation on the numbers and output the result.
Source: https://habr.com/ru/post/122259/