I'm trying to make a program in Haskell that compares two [Char] and returns a [Integer] of all the positions that the Chars are the same.
commons :: [Char] -> [Char] -> [Integer]
commons a b = case (a, b) of
([], _) -> []
(_, []) -> []
(_, _) -> fcommons 0 a b []
fcommons n s1 s2 set = case (s1, s2) of
([], _) -> set
(_, []) -> set
(a:b, c:d) -> if a==c then fcommons n+1 b d (set:n)
else fcommons n+1 b d set
I end up getting this error:
ERROR "commons.hs":7 - Type error in function binding
*** Term : fcommons
*** Type : [a] -> [b] -> [b] -> a -> a
*** Does not match : [a] -> a
*** Because : unification would give infinite type
I'm new to Haskell and have no idea why this is happening.
Name:
Anonymous2007-09-05 21:30 ID:Ci6wlsOk
Also, sorry if this is a really shitty way to write hscode.
Name:
Anonymous2007-09-05 21:53 ID:7eHhb3ll
yes, it's really shitty, so shitty it looks like a joke.
commons :: [Char] -> [Char] -> [Integer]
commons a b = fcommons 0 a b []
fcommons _ [] _ set = set
fcommons [] _ _ set = set
fcommons n (a:b) (c:d) set | a == c = fcommons (n+1) b d (set:n)
| otherwise = fcommons (n+1) b d set
that is the same thing, rewritten in a good style. anyway, the error is that you're doing set:n, but it's actually n:set. why?
it's head:tail, the head is an element of the same type as the elements of the list, in this case, an integer. and tail must be a list.
still, using an accumulator is not how it's done. the "good" way (in haskell, at least) is:
commons :: [Char] -> [Char] -> [Integer]
commons a b = fcommons 0 a b
fcommons _ [] _ = []
fcommons [] _ _ = []
fcommons n (a:b) (c:d) | a == c = n : fcommons (n+1) b d
| otherwise = fcommons (n+1) b d
this still can be done better, but I won't get into harder ground.
commons a b = [i|(i,eq) <- zip [0..] $ zipWith (==) a b, eq]
Name:
Anonymous2007-09-06 1:03 ID:IMCJl5DK
>>5
That's clever! I've spent like 3 minutes or so on it until I got that eq gets either True or False and i|(i,eq) doesn't yield number if eq /= True. Thanks >>5. Haskell rules.
Name:
Anonymous2007-09-06 21:52 ID:DwOmTfJ8
So, breaking it down:
Prelude> zipWith (==) "abcd" "xbxde"
[False,True,False,True]
Prelude> zip [0..] $ zipWith (==) "abcd" "xbxde"
[(0,False),(1,True),(2,False),(3,True)]