Couldn't match expected type - haskell

I have the following Haskell program:
catlines = unlines . zipWith (\(n,l) -> show n ++ l) [0..]
main = putStrLn $ catlines ["A", "B"]
When I try to compile it, GHC gives the following error:
catlines.hs:1:41:
Couldn't match expected type `b0 -> String' with actual type `[a0]'
In the expression: show n ++ l
In the first argument of `zipWith', namely
`(\ (n, l) -> show n ++ l)'
In the second argument of `(.)', namely
`zipWith (\ (n, l) -> show n ++ l) [0 .. ]'
From what I know, this should compile. I have no idea what's wrong.

The problem is that the function passed to zipWith should take two arguments, not a tuple. Try it like this:
zipWith (\n l -> show n ++ l)

Related

Getting the error "Non type-variable argument in the constraint: Integral [a2]"

I'm trying to implement the luhn algorithm using the following code:
luhn :: Int -> Bool
luhn x = (tail $ show (foldl (\acc x -> acc + (read x :: Int)) 0 (foldr doEncrypt [] $ zip [0..] (show x)))) == "0"
where
doEncrypt (i,y) acc = if not(even i)
then head(((uncurry (+) . (`divMod` 10) . (*2)) y)) : acc
else (head y) : acc
I now got stuck with the following error:
• Non type-variable argument in the constraint: Integral [a2]
(Use FlexibleContexts to permit this)
• When checking the inferred type
doEncrypt :: forall a1 a2.
(Integral a1, Integral [a2]) =>
(a1, [a2]) -> [a2] -> [a2]
In an equation for ‘luhn’:
luhn x
= (tail
$ show
(foldl
(\ acc x -> acc + (read x :: Int))
0
(foldr doEncrypt [] $ zip [0 .. ] (show x))))
== "0"
where
doEncrypt (i, y) acc
= if not (even i) then
head (((uncurry (+) . (`divMod` 10) . (* 2)) y)) : acc
else
(head y) : acc
I see that the error suggests that the second part of the tuple (a2) is a "Non type-variable argument". However, Haskell seems to identify this a2 argument as an Integral while in fact it is a Char. How can I tell Haskell that this is a Char and that Haskell shouldn't worry any further about this variable's type? Or is there something else I'm not understanding which causes this error?
Edit:
When I remove the (head y) and replace it by y I get instead the following error:
• Couldn't match type ‘Char’ with ‘[Char]’
Expected type: [String]
Actual type: [Char]
• In the third argument of ‘foldl’, namely
‘(foldr doEncrypt [] $ zip [0 .. ] (show x))’
In the first argument of ‘show’, namely
‘(foldl
(\ acc x -> acc + (read x :: Int))
0
(foldr doEncrypt [] $ zip [0 .. ] (show x)))’
In the second argument of ‘($)’, namely
‘show
(foldl
(\ acc x -> acc + (read x :: Int))
0
(foldr doEncrypt [] $ zip [0 .. ] (show x)))’
There where multiple things wrong with my solution, but finally the following code works!
luhn :: Int -> Bool
luhn x = (tail $ show (foldl (\acc x -> acc + (digitToInt x)) 0 (foldr doEncrypt [] $ zip [0..] (show x)))) == "0"
where
doEncrypt (i,y) acc = if not(even i)
then (head $ show(((uncurry (+) . (`divMod` 10) . (*2)) (digitToInt y)))) : acc
else y : acc
Thanks a lot to #WillemVanOnsem for your pointers, without I probably wouldn't have solved this!

Haskell type matching error

I have defined a couple of type synonyms as follows:
type Potential = Float
type Label = String
type LabelSet = [String]
In addition I have defined the following type and type synonym:
data VariableNode = VariableNode Label Potential LabelSet
type PGM = [VariableNode]
Finally, the following function to construct a graph:
makePGM :: [((Label, Potential), LabelSet)] -> PGM
makePGM (x:xs) = (VariableNode (fst . fst x) (snd . fst x) (snd x)) : makePGM xs
makePGM [] = []
In the above function, a list of tuples is provided where the first element of the tuple is another tuple and the second a list, as per the functions type signature.
I am new to Haskell so am having some difficulty in deciphering the following error messages:
Prelude> :l Graph.hs
[1 of 1] Compiling Graph ( Graph.hs, interpreted )
Graph.hs:14:33: error:
• Couldn't match type ‘a0 -> c0’ with ‘[Char]’
Expected type: Label
Actual type: a0 -> c0
• Probable cause: ‘(.)’ is applied to too few arguments
In the first argument of ‘VariableNode’, namely ‘(fst . fst x)’
In the first argument of ‘(:)’, namely
‘(VariableNode (fst . fst x) (snd . fst x) (snd x))’
In the expression:
(VariableNode (fst . fst x) (snd . fst x) (snd x)) : makePGM xs
Graph.hs:14:39: error:
• Couldn't match expected type ‘a0 -> (c0, b0)’
with actual type ‘(Label, Potential)’
• Possible cause: ‘fst’ is applied to too many arguments
In the second argument of ‘(.)’, namely ‘fst x’
In the first argument of ‘VariableNode’, namely ‘(fst . fst x)’
In the first argument of ‘(:)’, namely
‘(VariableNode (fst . fst x) (snd . fst x) (snd x))’
Graph.hs:14:47: error:
• Couldn't match type ‘a1 -> c1’ with ‘Float’
Expected type: Potential
Actual type: a1 -> c1
• Probable cause: ‘(.)’ is applied to too few arguments
In the second argument of ‘VariableNode’, namely ‘(snd . fst x)’
In the first argument of ‘(:)’, namely
‘(VariableNode (fst . fst x) (snd . fst x) (snd x))’
In the expression:
(VariableNode (fst . fst x) (snd . fst x) (snd x)) : makePGM xs
Graph.hs:14:53: error:
• Couldn't match expected type ‘a1 -> (a2, c1)’
with actual type ‘(Label, Potential)’
• Possible cause: ‘fst’ is applied to too many arguments
In the second argument of ‘(.)’, namely ‘fst x’
In the second argument of ‘VariableNode’, namely ‘(snd . fst x)’
In the first argument of ‘(:)’, namely
‘(VariableNode (fst . fst x) (snd . fst x) (snd x))’
Failed, modules loaded: none.
I have concluded that there are type mismatches but am not clear how so, given the types I have defined and the functions type signature.
The problem is that f . g x is f . (g x). Therefore, the types don't match:
fst . fst ((1,2),3)
== fst . (fst ((1,2),3))
== fst . (1,2)
== ???? (.) expects a function, not a value
You either have to use parentheses around fst . fst or $:
-- reminder:
(.) :: (b -> c) -> (a -> b) -> a -> c
(.) f g x = f (g x)
($) :: (a -> b) -> a -> b
($) f x = f x
(fst . fst) x
== fst (fst x)
fst $ fst x
== fst (fst x)
You can also combine both, e.g. fst . fst $ x, since the precedence of $ is low.
Of course, this is a useful exercise to do, and as a result of making this mistake you've learned to better understand operator precedence and parsing in Haskell. However, once you have more experience you'll realize you could have avoided the problem, and wound up with simpler code as a result, by using pattern matching instead of composing calls to fst and snd:
makePGM :: [((Label, Potential), LabelSet)] -> PGM
makePGM (((label, potential), set):xs) = VariableNode label potential set : makePGM xs
makePGM [] = []
Now the code is shaped like the data it consumes, and you get to give descriptive names to the values you work with.
Another improvement comes from observing that this recursive pattern is very common: you do something to each item in the list, independent of each other, and construct a list of the results. In fact, that is exactly what map does. So you could write a function that deals with only one of these PGM items at a time, and then use map to extend it to a function that works on a list of them:
makePGM :: [((Label, Potential), LabelSet)] -> PGM
makePGM = map go
where go ((label, potential), set) = VariableNode label potential set

Haskell in append few list together

I want to the value of one element in a List , So I did the
changePoint :: (Int,Int) -> [[[Char]]] -> [[Char]]
changePoint (x,y) maze = let
linelement = maze !! (y-1)
-- value ["X"," "," ",...," ","X"]
rowelement = chunksOf 1 $ head linelement
-- type:[[a]]; value ["X"," "," "," "," "," "," "," "," "," "," "," "," ","X"]
l = length rowelement
list = take (x-1) rowelement
-- in take (x-1) rowelement -- ["X"]
in take (x-1) rowelement ++ (["."] : (drop (x) rowelement))
I want to append the list "take (x-1) rowelement" and "["."]" and "drop (x) rowelement", the type of list will be [[a]]
Couldn't match expected type ‘Char’ with actual type ‘[Char]’
In the expression: "."
In the first argument of ‘(:)’, namely ‘["."]’
In the second argument of ‘(++)’, namely
‘(["."] : (drop (x) rowelement))’ Failed, modules loaded: none.
x = 2 .
I know the problem is "["."]",but I really don't how to fix it .
The true return should be ["X","."," "," ",..,"X" ]
In GHCI, you can use :t somefunction to get the type of somefunction.
Here, the problem is with (:), lets see what GHCI tells us.
Prelude λ> :t (:)
(:) :: a -> [a] -> [a]
So (:) takes an a, a list of as and returns a new list. Specialized for the use case at hand, (:) has type [Char] -> [[Char]] -> [[Char]] (because a = [Char]). But ["."] has type [[Char]], so it does not match what's expected for (:).
Now, if you use take (x-1) rowelement ++ ("." : (drop (x) rowelement)) (note the missing [] around "."), the function should compile fine.
Either use:
(take (x-1) rowelement) ++ ["."] ++ (drop x rowelement)
Or
(take (x-1) rowelement) ++ ("." : (drop x rowelement))
The [ and ] are not necessary

Haskell: Couldn't match type [Int] with Int

Hi here is my code below.
data Treeof a = Node Int a [Treeof a] deriving (Eq,Show)
add_score :: Int -> Treeof a -> [[Int]]
add_score 0 (Node i a xs) = [[0]]
add_score n (Node i a xs) = [i]:[(map (add_score (n-1)) xs)]
I trying to obtain the Int stored in each Node of a Tree and store it in a list of lists but get the error shown below and I'm unsure why.
Couldn't match type `[[Int]]' with `Int'
Expected type: Treeof a -> Int
Actual type: Treeof a -> [[Int]]
In the first argument of `map', namely `(add_score (n - 1))'
In the expression: (map (add_score (n - 1)) xs)
Failed, modules loaded: none.
EDIT: Changed [i]:[(map (add_score (n-1)) xs)] to [i]:(map (add_score (n-1)) xs)
And getting a similar error
Couldn't match type `[Int]' with `Int'
Expected type: Treeof a -> [Int]
Actual type: Treeof a -> [[Int]]
In the first argument of `map', namely `(add_score (n - 1))'
In the second argument of `(:)', namely
`(map (add_score (n - 1)) xs)
Failed, modules loaded: none.
xs has type [TreeOf a]. Clearly, you can map add_score (n-1) over such a list as you did, since this takes TreeOf a as an argument.
But what's the result? Well, a list of whatever the result of a single add_score (n-1) is. But that's already a [[Int]], so you get
map (add_score $ n-1) xs :: [ [[Int]] ]
which is one nesting level too much. Now wrapping this in another singleton list is clearly counterproductive. On the contrary, you need to flatten one list level. There are at least three ways to do this:
Concatenate the outer lists.
[i] : (concat $ map (add_score $ n-1) xs)
this can be more nicely written with =<< (aka concatMap), as
[i] : (add_score (n-1) =<< xs)
Concatenate the inner lists.
[i] : (map (concat . add_score (n-1)) xs)
Sum up the innermost list.
[i] : (map (map sum . add_score (n-1)) xs)
You must know yourself which behaviour you want; the first seems most useful to me.
The error is simply telling you there is one too many (or one too few) layers of lists somewhere.
Why are you putting map ... as a single element of a list:
[(map (add_score (n-1)) xs)]
At first blush, it appears you want:
(map (add_score (n-1)) xs)
But then since add_source fully applied yields a [[Int]], mapping it will be of type [[[Int]]] (thanks #Carsten). You might be after:
concatMap (add_score (n-1)) xs
That will concatenate the list and yield a result of type [[Int]].

Haskell head/tail vs pattern matching

Here are two pieces of code.
Working:
joins :: [String] -> String -> String
joins [] _ = ""
joins [x] _ = x
joins xs d = head xs ++ d ++ (joins (tail xs) d)
Not working:
joins :: [String] -> String -> String
joins [] _ = ""
joins [x] _ = x
joins [x:xs] d = x ++ d ++ (joins xs d)
The error log for the latter is:
test.hs:4:18:
Couldn't match expected type `[Char]' with actual type `Char'
In the first argument of `(++)', namely `x'
In the expression: x ++ d ++ (joins xs d)
In an equation for `joins':
joins [x : xs] d = x ++ d ++ (joins xs d)
test.hs:4:35:
Couldn't match type `Char' with `[Char]'
Expected type: [String]
Actual type: [Char]
In the first argument of `joins', namely `xs'
In the second argument of `(++)', namely `(joins xs d)'
In the second argument of `(++)', namely `d ++ (joins xs d)'
What am I missing here?
Use parentheses, not brackets:
-- vvvvvv
joins (x:xs) d = x ++ d ++ (joins xs d)
The pattern [x:xs] matches only with a list of length one, whose single element is a nonempty list x:xs.
Since yours is a list of strings, [x:xs] matches with ["banana"] (where x='b', xs="anana"), with ["a"] (x='a', xs="") but not with ["banana", "split"] nor with [""].
This is clearly not what you want, so use plain parentheses.
(By the way, the parentheses in ... ++ (joins xs d) are not needed: function application binds more than any binary operator in Haskell.)

Resources