formal_list: typ ID { [($1,$2)] }
| formal_list COMMA typ ID { ($3,$4) :: $1 }
What does the :: operator mean?
For instance: a :: b
Is the meaning that we add a to b?
The :: operator constructs a list. At the left is a list element (the head), at the right is a list (the tail). The operator is right associative, so you can write: 3 :: 4 :: []. The empty list is denoted by [].
Related
Why can't I use [1] :: [1] but [1] :: [1] :: []?
I tried to do [1] :: [1]. Got this error:
Error: This expression has type int but an expression was expected of type int list
When I do [1] :: [1] :: [] I get this: - : int list list = [[1]; [1]]
[] is the empty list
x :: [] is the same as [x]
x :: [y] is the same as x :: y :: [] and as [x; y]
With your particular examples:
[1] :: [] is the same as [[1]]
[1] :: [1] :: [] is the same as [[1]; [1]]
[1] :: [1] would be the same as [1] :: 1 :: [] and [[1]; 1], but you can't have a list containing mixed types.
#Stef's answer is good. Here is another similar answer.
First, :: is a right associative operator with two operands. The left operand can have any type and the right operand must be a list of that type. The result of the operator is a list with the same type as the right operand.
Second [] is an empty list that can have any element type.
Written out fully, lists look like this: a :: b :: c :: ... :: []. But they can be written more conveniently as [a ; b ; c ; ... ]. The empty list (as mentioned) is []. A list of one element looks like this: [x].
Finally, the elements of a list must all be the same type.
So here is your first case:
[1] :: [1] :: []
This is a valid list because the elements are all the same type (necessarily since they're the same) and the :: operators are used correctly with a type on the left and a list of that type on the right. Note that this is only the case because :: is right associative. So the rightmost :: is applied first. You could also write this list as [ [1] ; [1] ].
Here is your second case:
[1] :: [1]
The operator :: here is not applied correctly. The requirement is that the type of the value on the right be a list of the type of the value on the left. Another way to say this is that int list is not a list whose elements are type int list. To make this valid you can change the left value to be 1 (then you have int and int list as operands of ::) or the right value to be [[1]] (then you have int list and int list list as operands of ::).
I'm very new on Haskell, and I'm trying the following:
To obtain [1,2,3] from [[1,2,3],[4,5,6]]?
example :: [[a]] -> [a]
example [] = []
example [x:xs] = [x]
This example is returning [1] when input is [[1,2,3]] and if I add an other element in the main List, like [[1,2,3],[3,4,5]] then I have a Non-exhaustive pattern function.
You are quite close. In fact what you here want is some sort of "safe" head.
A list [a] has two constructors:
the empty list [], you cover this in the first case; and
the "cons" (x:xs).
It looks like you cover that in the second case, but in fact you do not: you put the pattern within square brackets. As a result, Haskell interprets your pattern as [(x:xs)]. So it thinks you match a singleton list (a list with one element), and that x is the head of the sublist, and xs the tail of the sublist.
In fact you want to cover (x:xs). If we use this pattern, there is another problem: x is the head of the list, so it has type [a]. Therefore we should return x, not [x], since in the latter case, we would wrap the sublist back in a list.
So a correct function is:
example :: [[a]] -> [a]
example [] = []
example (x:_) = x -- round brackets, x instead of [x]
Note that since we are not interested in the tail here, we use an underscore _. If you compile with all warnings (-Wall, or more specific -Wunused-matches) Haskell will otherwise complain about the fact that you declare a variable that you do not use.
Generalizing to a safeHead function
We can generalize this to some sort of generic safeHead :: b -> (a -> b) -> [a] -> b function:
safeHead :: b -> (a -> b) -> [a] -> b
safeHead d _ [] = d
safeHead _ f (x:_) = f x
Here we thus pass three arguments to safeHead: a value (of type b) we should return in case the list is empty; a function to post-process the head (type a -> b), and the list to process. In that case the example is equivalent to:
example :: [[a]] -> [a]
example = safeHead [] id
But we can also return a Maybe [a] here:
example2 :: [a] -> Maybe a
example2 = safeHead Nothing Just
I have a question about head, tail, init and last.
The following works in GHCi:
Prelude Data.List Data.Char> let n = [1..10] in (head n : tail n)
[1,2,3,4,5,6,7,8,9,10]
As expected, I get the whole list. So this should work for init and last too,
right?
Prelude Data.List Data.Char> let n = [1..10] in (init n : last n)
<interactive>:39:1:
Non type-variable argument in the constraint: Enum [[a]]
(Use FlexibleContexts to permit this)
When checking that ‘it’ has the inferred type
it :: forall a. (Enum a, Enum [[a]], Num a, Num [[a]]) => [[a]]
If I look at the type signatures for the functions, then head and last
look the same -- they both return an element. Also init and tail look
the same, because they both return lists.
Prelude Data.List Data.Char> :info head
head :: [a] -> a -- Defined in ‘GHC.List’
Prelude Data.List Data.Char> :info tail
tail :: [a] -> [a] -- Defined in ‘GHC.List’
Prelude Data.List Data.Char> :info init
init :: [a] -> [a] -- Defined in ‘GHC.List’
Prelude Data.List Data.Char> :info last
last :: [a] -> a -- Defined in ‘GHC.List’
So what does Non type-variable argument in the constraint: Enum [[a]] mean?
If I do init n or last n without the construction of a new list, I get
[1..9] and 10.
Ahh snap, : takes an element and the rest like in x:xs, not a list and the last element, like in xs:x.
Prelude Data.List Data.Char> :info :
data [] a = ... | a : [a] >·-- Defined in ‘GHC.Types’
infixr 5 :
data [] a = ... | a : [a] >·-- Defined in ‘GHC.Types’
infixr 5 :
I still would like to know how you understand GHCi error messages and I have to wait 2 days to accept my own answer anyway.
Edit: I get that x and xs are only variable names chosen by convention, and (xs:_) would match the head but is unconventionally/confusingly named.
Edit 2: I upvoted and accepted Daniel Wagner's answer, because he explained the error message step by step. Really nice! Thank you!
It is true that head/last and tail/init have identical types. So if you had simply swapped out last for head and init for tail, you would have had no problem:
> let n = [1..10] in last n : init n
[10,1,2,3,4,5,6,7,8,9]
But you didn't. You did both that swap and another: you changed the order of arguments to :. It so happens that : doesn't take two arguments of the same type:
> :t (:)
(:) :: a -> [a] -> [a]
So this last swap is not okay! In fact, if you give n a slightly more specific type signature, ghci will give a better error:
> let n :: [Integer]; n = [1..10] in init n : last n
<interactive>:1:50:
Couldn't match type ‘Integer’ with ‘[[Integer]]’
Expected type: [[[Integer]]]
Actual type: [Integer]
In the first argument of ‘last’, namely ‘n’
In the second argument of ‘(:)’, namely ‘last n’
This error is still not 100% clear, but I think with a bit of puzzling you can see what it's complaining about: since init n :: [Integer], and (:) :: [Integer] -> [[Integer]] -> [[Integer]], it's expecting last n :: [[Integer]] and therefore n :: [[[Integer]]]. But you explicitly said n :: [Integer], a conflict.
Now, what about the error it actually gave you in your case? Well, the clue is in the type of [1..10]:
> :t [1..10]
[1..10] :: (Enum t, Num t) => [t]
Notice that [1..10] is polymorphic. Moreover, it is used twice in your expression, and so it can be given separate monomorphic types in the two uses. So [1..10] is instantiated with two different types in the sequel!
Now I think you can start to see where the error you got comes in. It's trying to find a type a for which:
Enum a -- this is needed to do the .. part of init [1..10]
Num a -- this is needed to do the 1 and 10 parts of init [1..10]
Enum [[a]] -- if init n :: a, then to have init n : last n be well-typed, we must have last n :: [a] and hence the second occurrence of n must have n :: [[a]]; then the Enum constraint is needed for the .. part of last [1..10]
Num [[a]] -- by similar reasoning, this is needed to do the 1 and 10 parts of last [1..10]
But these constraints together are hard to satisfy -- certainly there's no instance of Enum and Num for lists in scope in the Prelude or Data.List. So it complains.
In larger programs there is more type information (implicit and explicit) allowing the compiler to do a better job inferring types than in one-line snippets provided to GHCi. As a result, the errors you see in GHCi are not representative of what is typically observed when building a full program.
That said, it's no excuse for the awfulness that is the error you posted:
Prelude> let n = [1..10] in (init n : last n)
<interactive>:8:1:
Non type-variable argument in the constraint: Enum [[a]]
(Use FlexibleContexts to permit this)
When checking that ‘it’ has the inferred type
it :: forall a. (Enum a, Enum [[a]], Num a, Num [[a]]) => [[a]]
So there is a lot of polymorphism involved in your own line. You have lists of Num a (Num a => [a]) where the type variable a must itself be alist since you've used : last n where last n :: [_] ~ a. So this, combined with the fact that .. in list comprehension implies an enum, is how we got to the horrible message.
Let's look at the simpler case where we've told GHCi our list is of type [Int]:
Prelude> let n = [1..10] :: [Int] in (init n : last n)
<interactive>:7:44:
Couldn't match type ‘Int’ with ‘[[Int]]’
Expected type: [[[Int]]]
Actual type: [Int]
In the first argument of ‘last’, namely ‘n’
In the second argument of ‘(:)’, namely ‘last n’
Ahh, much better. Column 44 is the n in last n. It says that last n :: Int. So the type of init n : when init n :: [Int] means our cons function type is (:) :: [Int] -> [[Int]] -> [[Int]]. But wait! [[Int]] needed for the argument of init n : does not match Int provided by last n!
I am trying to write a remove function, so that a user can type remove 'd' ["abc", "dc", "ad"] and get the output ["abc", "c", "a"].
My code is:
remove :: Eq a => a -> [[a]] -> [[a]]
remove a (x:xs) = filter (not.a) (x:xs)
But I get the following error message:
Occurs check: cannot construct the infinite type: a = [a] -> Bool
When generalising the type(s) for `remove'
What does the error message mean, and how can I change the second line so it works?
The type of filter is
filter :: (a -> Bool) -> [a] -> [a]
so the first argument you pass to filter must be a function from the element-type of the list to Bool. In
remove :: Eq a => a -> [[a]] -> [[a]]
remove a (x:xs) = filter (not.a) (x:xs)
you say
a has type a, and the list has type [[a]], i.e. the list-element type is [a], and
not . a, the first argument to filter, has type [a] -> Bool.
Together, these imply
a = [a] -> Bool
but that is an infinite type.
You probably meant something like filter (not . (a `elem`)), or equivalently filter (a `notElem`), if the filter is meant to work on the outer list, or map (filter (/= a)) if you want to remove an element from each of the contained lists.
You state that the argument a is any type that supports equality.
But you then use it in a boolean expression: not . a.
The type of not is :: Bool -> Bool, so a must be of type Bool. But you already said that no, it was of type Eq t => t.
So that's a type error.
I think you mean to filter all elements that do not equal a, which would be:
remove a xs = filter (/= a) xs
However, your input is also a nested list, so you have to map the filter over the inner elements:
remove a xs = map (filter (/= a)) xs
I've got a function here that is meant to look through a list of tuples and find the second value in the tuple by taking in the first value. Here's the function so far:
lookup :: String -> [(String,String)] -> String
lookup _ _ [] = "Not found"
lookup x y zs = if (notFound x zs)
then "Not found"
else (head [b | (a,b) <- zs, (a==x)])
The notFound function just returns a Bool as true if there is no tuple containing the given first string. Problem is, I get this type error in Hugs:
ERROR "find.hs" (line 22): Type error in explicitly typed binding
*** Term : lookup
*** Type : String -> [(String,String)] -> [a] -> String
*** Does not match : String -> [(String,String)] -> String
I'm thinking it's something to do with the dummy "Not found" value having a different type to the string from the generated list, but I'm not sure.
I think your explicit type-declaration is wrong. You have:
lookup :: String -> [(String,String)] -> String
but I think it should be
lookup :: String -> String -> [(String,String)] -> String
Actually, after taking another look at it, it looks like you're not using the 2nd parameter "y". So you could remove it and the underscore like so
lookup :: String -> [(String,String)] -> String
lookup _ [] = "Not found"
lookup x zs = if (notFound x zs)
then "Not found"
else (head [b | (a,b) <- zs, (a==x)])
This will allow you to keep the type declaration you have.
by the way, did you know that Haskell Prelude already has a "lookup" function to look up entries in an association list? here is the type signature (it is more general, accepting any key type which instances Eq):
lookup :: (Eq a) => a -> [(a,b)] -> Maybe b
so your function would accomplish something like the below
myLookup x zs = Maybe.fromMaybe "Not found" $ lookup x zs
At a glance, it looks like maybe the second parameter should be removed (the 'y' and the second underscore)? lookup is declared to take two parameters, not three.