In the code:
oneChar :: Char -> Doc
oneChar c = case lookup c simpleEscapes of
Just r -> text r
Nothing | mustEscape c -> hexEscape c
| otherwise -> char c
where mustEscape c = c < ' ' || c == '\x7f' || c > '\xff'
simpleEscapes :: [(Char, String)]
simpleEscapes = zipWith ch "\b\n\f\r\t\\\"/" "bnfrt\\\"/"
where ch a b = (a, ['\\',b])
r isn't being passed to oneChar. Where does r come from?
lookup c simpleEscapes returns a Maybe String value, which can be either Nothing or Just <a string>. r is the string contained in the Just, as defined by the line:
Just r -> text r
The case keyword introduces a pattern match, which has the form case EXPR of (PATTERN -> EXPR)+. So Just r is a pattern, that matches the result of lookup c simpleEscapes of. In a pattern, variables can be bound. Basically this means, if lookup c simpleEscapes of returns a Just then r will be bound to the value inside that Just and the result of the expression will be text r.
If you're asking where the identifier is introduced, it's bound by the pattern match in the case statement, the same way the identifier c is bound by the pattern match in the function definition.
Any pattern match can introduce a new identifier for the associated expression:
(\(Just x) -> x) foo
let (Just x) = foo in x
f (Just x) = x
case foo of
Just x -> x
...all of those introduce a new identifier named x. In fact, they're all pretty much equivalent, because the compiler converts all of them into case blocks under the hood.
You're using a case statement on the value returned by lookup c simpleEscapes, which is of type Maybe. Maybe has two data constructors: Just and Nothing. The Just data constructor is parameterized by one value, the Nothing data constructor has no parameters.
So in this case, r is the formal parameter to the Just data constructor: its the actual value in the returned value from lookup.
Related
So, I have been trying to use SDL to make a simple GUI. This is so that I start to understand how to use haskell. In this case, I was using https://github.com/palf/haskell-sdl2-examples/blob/master/examples/lesson04/src/Lesson04.hs as reference.
Pay attention, in particular to payloadToIntent on line 72.
payloadToIntent :: SDL.EventPayload -> Intent
payloadToIntent SDL.QuitEvent = Quit
payloadToIntent (SDL.KeyboardEvent k) = getKey k
payloadToIntent _ = Idle
This works perfectly. However, when I change the code to the following, it produces an error. Why does it happen, as to my (admittedtly novice) eyes, this looks equivalent.
payloadToIntent e
| e == SDL.QuitEvent = Quit
| e == SDL.KeyboardEvent k = getKey SDL.KeyboardEvent k
| otherwise = Idle
Error:
src/Events/Intent.hs:15:28: error:
Variable not in scope: k :: SDL.KeyboardEventData
|
15 | | e == SDL.KeyboardEvent k = getKey SDL.KeyboardEvent
| ^
I am using these language extensions: OverloadedStrings, GADTs, PatternGuards
So why did this happen? How could I fix this? Which one would be more idiomatic haskell?
(==) is a function that takes two values of the same type and compares them for equality, returning a Bool. SDL.KeyboardEvent k is not a value of any type (since k is unbound), so you can't compare it with (==).
The idiomatic "choice" is the one that works, i.e. pattern matching. If you want something that has a similar appearance, you can pattern match with case...of instead:
payloadToIntent e = case e of
SDL.QuitEvent -> Quit
SDL.KeyboardEvent k -> getKey k
_ -> Idle
The key idea here is: patterns define variables, bringing them into scope, while expressions do not, requiring all the variables in them to be already defined.
The guard e == SDL.KeyboardEvent k is a boolean valued expression, not a pattern. This is calling function (==) with two arguments: e and SDL.KeyboardEvent k. Your definition, to the compiler, looks like:
payloadToIntent e
| isEqual e SDL.QuitEvent = Quit
| isEqual e (SDL.KeyboardEvent k) = getKey SDL.KeyboardEvent k
| otherwise = Idle
The compiler can not call the equality-test function without passing it the arguments. For that, it needs variable k to be in scope, i.e., to be defined somewhere else.
To stress the point, consider this non-working code:
isSquare :: Int -> String
isSquare n | n == m*m = "It's the square of " ++ show m
| otherwise = "It isn't a square"
This would magically invert the squaring, if possible. That is, however, asking too much to the compiler, which won't magically solve the equation for us. (Indeed, the solution could even fail to be unique!)
As an even more cumbersome case:
f x | x == F y || x == G z = ...
Even if this worked, can we use y or z in the final ...? Probably not. Why should then this be allowed?
Finally, note that, even in those cases where it could work, allowing expressions guards to define variables could be a bad idea. Consider this:
c :: Int
c = 7
f x | x == F c = "Hi"
| otherwise = "there"
Now, is the c in F c a new local variable which is defined on the spot, or is it the constant 7 defined above? If we call f (F 6) do we get Hi (c was a new variable) or there (c was 7)?
Pattern matching avoids this issue by requiring a distinct syntax.
I am trying to make my own custom data type in Haskell.
I have the following data types:
type Length = Integer
type Rotation = Integer
data Colour = Colour { red, green, blue, alpha :: Int }
deriving (Show, Eq)
I am trying to make a custom data type that can be either one of the data types above. I have the following:
data Special
= L Length
| R Rotation
| Col Colour
deriving (Show, Eq)
However, I would like to be able to extract the Length, Rotation and Colour value if I have an instance of the Special data type.
If I had:
L length
Would length here be of type Special or of type Length? If length is of type Special is there any way to extract it so it's of type Length?
For example, is the following code valid?
takeL (x:xs)
| x == (L length) = length
Any insights are appreciated.
For the expression L length to be valid, length would have to be a Length (because L :: Length -> Special).
takeL (x:xs)
| x == (L length) = length
is not valid. Unless you've redefined length somewhere, length is a function [a] -> Int from the standard library, so L length is a type error.
I think what you're trying to do here is just pattern matching:
takeL (L length : xs) = length
The data type definition
data Special =
reads: Special is a new type such that to create a value of type Special,
L Length
call L l where l is a value of type Length; or
| R Rotation
call R r where r is a value of type Rotation; or
| Col Colour
call Col c where c is a value of type Colour.
To analyze a value of type Special, there are three cases to consider:
foo :: Special -> ...
foo val =
case val of
L l -> ...
l is a value of type Length, in the case val was actually L l; or
R r -> ...
r is a value of type Rotation, in the case val was actually R r; or
Col c -> ...
c is a value of type Colour, in the case val was actually Col c.
The case syntax in function definitions can also be expressed with the pattern based clauses:
foo :: Special -> ...
foo (L l) = ...
foo (R r) = ...
foo (Col c) = ...
I have recently started learning Haskell and I have encountered a problem with dictionaries. I use a key to get the integer number from the dictionary, and GHCi prints an error "Couldn't match type Char with [Char]" on the line where I use a first element of the string as key for a dictionary. Here is the code:
import Data.Map
mapRomantoInt :: Map String Int
mapRomantoInt = fromList[("I",1),("V",5),("IX",9),("X",10),("L",50),("C",100),("D",500),("M",1000)]
romanToInt :: String -> Int
romanToInt _ = 0
romanToInt c = if length c == 1 then mapRomantoInt ! head c else
let first = mapRomantoInt ! head c
second = mapRomantoInt ! (c !! 1)
others = romanToInt(tail c)
in if first < second then others - first else others + first
In Haskell, String is a synonym for [Char].
The c in romanToInt has the type String, i.e. [Char].
The type of head is [a] -> a, so head c has the type Char.
The type of (!) is Ord k => Map k a -> k -> a. In this case, mapRomantoInt has the type Map String Int, so the k in question must be String.
The function call mapRomantoInt ! head c, however, tries to pass a Char instead of a [Char] (String).
There are other problems with the code in the OP, but try to fix the compilation error(s) first.
I built a data structure in form of a function that outputs certain strings in response to certain input strings like this:
type mydict = String -> String
emptydict :: mydict
emptydict _ = "not found"
Now I can add entries into this dictionary by doing the following:
addentry :: String -> String -> mydict -> mydict
addentry s1 s2 d s
| s1 == s = s2
| otherwise = d s
To look for s2's I can simply enter s1 and look in my dictionary
looky :: String -> mydict -> String
looky s1 d = d s1 --gives s2
My goal is now to create another function patternmatch in which I can check which s1's are associated with an s2 that starts with a certain pattern. Now the pattern matching itself isn't the problem, but I am not sure how can I keep track of the entries I entered, i.e. for which input is the output not "not found" ?
My idea was to try to keep track of all the s1's I entered in the addentry function and add them to a separate list. In patternmatch I would feed the list elements to looky, such that I can get back the associated s2's and check whether they match the pattern.
So my questions:
1) Is this list building approach good or is there a better way of identifying the inputs for which a function is defined as something other than "not found"?
2) If it is the right approach, how would I keep track of the s1's? I was thinking something like:
addentry s1 s2 d s
| last (save s1) == s = s2
| otherwise = d s1
And then save s1 being a function generating the list with all s1's. last (save s1) would then return the most recent s1. Would appreciate any help on implementing save s1 or other directions going from here. Thanks a lot.
Your design is hard-coded such that the only criteria for finding a key is by presenting the same exact key. What you need is a more flexible approach that lets you provide a criteria other than equality. I took the liberty of making your code more general and using more conventional names for the functions:
import Prelude hiding (lookup)
-- instead of k -> Maybe v, we represent the dictionary as
-- (k -> Bool) -> Maybe v where k -> Bool is the criteria
-- on which to match the key. by using Maybe v we can signal
-- that no qualifying key was found by returning Nothing
-- instead of "not found"
newtype Dict k v = Dict ((k -> Bool) -> Maybe v)
empty :: Dict k v
empty = Dict $ const Nothing
-- insert a new key/value pair
insert :: k -> v -> Dict k v -> Dict k v
insert k v d = Dict $ \f -> if f k then Just v else lookupBy f d
-- lookup using the given criteria
lookupBy :: (k -> Bool) -> Dict k v -> Maybe v
lookupBy f (Dict d) = d f
-- lookup using the default criteria (equality with some given key)
lookup :: Eq k => k -> Dict k v -> Maybe v
lookup k = lookupBy (k==)
-- your criteria
startsWith :: String -> String -> Bool
startsWith s = undefined -- TODO
lookupByPrefix :: String -> Dict String v -> Maybe v
lookupByPrefix = lookupBy . startsWith
I should mention that while this is a great exercise for functional programming practice and general brain-expansion, it's a terrible way to implement a map. A list of pairs is equivalent and easier to understand.
As a side note, we can easily define an instance of Functor for this type:
instance Functor (Dict k) where
fmap f d = Dict $ \g -> fmap f (lookupBy g d)
I have defined a binary tree:
data Tree = Null | Node Tree Int Tree
and have implemented a function that'll yield the sum of the values of all its nodes:
sumOfValues :: Tree -> Int
sumOfValues Null = 0
sumOfValues (Node Null v Null) = v
sumOfValues (Node Null v t2) = v + (sumOfValues t2)
sumOfValues (Node t1 v Null) = v + (sumOfValues t1)
sumOfValues (Node t1 v t2) = v + (sumOfValues t1) + (sumOfValues t2)
It works as expected. I had the idea of also trying to implement it using guards:
sumOfValues2 :: Tree -> Int
sumOfValues2 Null = 0
sumOfValues2 (Node t1 v t2)
| t1 == Null && t2 == Null = v
| t1 == Null = v + (sumOfValues2 t2)
| t2 == Null = v + (sumOfValues2 t1)
| otherwise = v + (sumOfValues2 t1) + (sumOfValues2 t2)
but this one doesn't work because I haven't implemented Eq, I believe:
No instance for (Eq Tree)
arising from a use of `==' at zzz3.hs:13:3-12
Possible fix: add an instance declaration for (Eq Tree)
In the first argument of `(&&)', namely `t1 == Null'
In the expression: t1 == Null && t2 == Null
In a stmt of a pattern guard for
the definition of `sumOfValues2':
t1 == Null && t2 == Null
The question that has to be made, then, is how can Haskell make pattern matching without knowing when a passed argument matches, without resorting to Eq?
Edit
Your arguments seem to revolve around the fact that Haskell is not indeed comparing the arguments of the function, but instead on the "form" and types of signature to know which sub-function to match. But how about this?
f :: Int -> Int -> Int
f 1 _ = 666
f 2 _ = 777
f _ 1 = 888
f _ _ = 999
When running f 2 9, won't it have to use Eq to know which one of the subfunctions is the right one? All of them are equal (contrary to my initial Tree example when we had Tree/Node/Null). Or is the actual definition of an Int something like
data Int = -2^32 | -109212 ... | 0 | ... +2^32
?
For pattern matching, Haskell uses the structure of the value and the constructors used. For example, if you evaluate
sumOfValues (Node Null 5 (Node Null 10 Null))
it checks the patterns from top to bottom:
the first one, Null, doesn't match because it has a different structure
the second one, (Node Null v Null), doesn't match because the last component, Null, has a different structure than (Node Null 10 Null) (pattern matching proceeds recursively)
the third one matches with v bound to 5 and t2 bound to (Node Null 10 Null).
Eq and the == operator it defines are an unrelated mechanism; making Tree an instance of Eq won't change how pattern matching works.
I think your thinking here is a bit backward: Pattern matching is the most basic way of using a value in Haskell; except for some basic types like Int, Eq is implemented using pattern matching, not the other way around.
Pattern matching and numbers
It turns out numeric literals are a special case. According to the Haskell report (link):
Matching a numeric, character, or string literal pattern k against a value v succeeds if v == k, where == is overloaded based on the type of the pattern.
Haskell knows what type constructor was used to construct a particular instance, and that's all it needs in order to pattern match successfully.
The thing you're missing is that you're assuming Null is some constant value like in C or Java. It's not — it's a constructor for the Tree type.
Pattern-matches do construction in reverse. Instead of you providing two values to the constructor and it gives you a value of the appropriate type, you provide a value of the type to the constructor and it gives you the constituent values that make up the type. The language knows which branch of the discriminated union was used to construct the value, so it can match against the correct pattern. Thus, there is no need for equality because it's all just constructors and variables — no actual values are being compared (or even necessarily evaluated).
With regards to your edit about Ints:
Yes, Int is basically a type with an obscenely large number of constructors along the lines of -2 | -1 | 0 | 1 | 2 | 3 | 4 …. It's a bit handwavy, but it works in practice.
At some point you need pattern matching when you don't want to use Eq. E.g. you could define
isEmpty :: Tree -> Bool
isEmpty Null = True
isEmpty _ = False
sumOfValues2 :: Tree -> Int
sumOfValues2 Null = 0
sumOfValues2 (Node t1 v t2)
| isEmpty t1 && isEmpty t2 = v
| isEmpty t1 = v + (sumOfValues2 t2)
| isEmpty t2 = v + (sumOfValues2 t1)
| otherwise = v + (sumOfValues2 t1) + (sumOfValues2 t2)
BTW, you don't need all that cases, just this:
sumOfValues :: Tree -> Int
sumOfValues Null = 0
sumOfValues (Node t1 v t2) = v + (sumOfValues t1) + (sumOfValues t2)
You can think of the data constructors as tags. To do a pattern matching on a value of Tree, the compiled code extracts the tag and just knows which branch to dispatch to. It doesn't care about the real value, so you don't need Eq.
Pattern matching depends on the syntax. E.g. if you write a pattern involving constructors, pattern matching by constructors is what you'll get. If you write a pattern involving litteral expressions (and litteral floating point values or integers are just that) you get an equality test (from the Eq class) using whatever overloaded definition of the (==) operator your type may provide.
So if you overload your Fred data type which is of class Num and has a constructor, also called Fred you could define equality against Integers by checking if the given Integer is 1. Now in that weird scenario, unless I'm overlooking something, the following ought to work:
getFred :: Fred -- get a Fred
getFred = Fred -- invoke the Fred constructor
testFred :: Fred -> Bool -- tests if Fred's equality operator considers 1 equal to Fred
testFred 1 = True -- overloaded (==) tests against 1, so should be true
testFred _ = False -- shouldn't happen, then...
isFredOne = testFred $ getFred -- returns True
I justify this type of thing to myself by saying that pattern matching is core to what Haskell is - the Eq typeclass is not.
So while there are features similar to pattern matching which require Eq, they are not pattern matching and could be implemented on top of pattern matching.