I want to write a replicate-like function that works like this :
repli "the" 3 = "ttthhheee" and
repli "jason" 4 = "jjjjaaaassssoooonnnn"
Here is the code that I wrote :
myrepli [] n = []
myrepli [x] 0 = []
myrepli [x] n = (x:(myrepli [x] (n-1)))
repli [] n = []
repli (x:xs) n = (myrepli x n) ++ (repli xs n)
The error I get is this :
Couldn't match expected type `[a]' against inferred type `Char'
Expected type: [[a]]
Inferred type: [Char]
In the first argument of `repli', namely `"jason"'
In the expression: repli "jason" 3
How can I fix this? Thanks.
For problems with types, here's a trick that has helped me immensely. Whenever I am completely baffled by a message like this, I do the following:
If there's a type signature on the function in question, remove it and see if anything changes. If it compiles, ask ghci what the type is (using :t). If it doesn't compile, at least the error message may differ enough to give you another clue.
If there's no type signature, add one. Even if it doesn't compile, the error message may give you another clue.
If that doesn't help, then temporarily add type declarations on each of the expressions in the function. (Often you'll need to break up some of the expressions to see what's really going on. You may also need to temporarily enable the ScopedTypeVariables pragma.) Compile again and check the error messages.
That last one is more work, but I've learned a lot from that exercise. It usually pinpoints the exact place where there's a mismatch between what I think the type is and what GHC thinks the type is.
So let's begin by adding type signatures to your code:
myrepli :: [a] -> Int -> [a]
myrepli [] n = []
myrepli [x] 0 = []
myrepli [x] n = (x:(myrepli [x] (n-1)))
repli :: [a] -> Int -> [a]
repli [] n = []
repli (x:xs) n = (myrepli x n) ++ (repli xs n) -- triggers a compiler error
Ah, now we get a compiler error:
amy.hs:9:27:
Couldn't match expected type `a' with actual type `[a]'
`a' is a rigid type variable bound by
the type signature for repli :: [a] -> Int -> [a] at amy.hs:7:10
In the first argument of `myrepli', namely `x'
In the first argument of `(++)', namely `(myrepli x n)'
In the expression: (myrepli x n) ++ (repli xs n)
The problem is in the call to myrepli x n. The function myrepli expects a list/string, but you're passing it a single character. Change that last line to:
repli (x:xs) n = (myrepli [x] n) ++ (repli xs n)
At that point you will find other errors in your code. But rather than fix your code, let me show you another way to do it:
repl (x:xs) n = (myReplicate x n) ++ (repl xs n)
repl [] _ = []
-- You could use the library function "replicate" here, but as a
-- learning exercise, we'll write our own.
myReplicate a n = take n (repeat a)
myrepli is expecting a list and an integer. However, the definition of repli calls it with x, which is an item, not a list of items.
I imagine you either want to change myrepli to take a single item as argument, or you want to change repli to pass [x] instead of just x. (I would suggest the former rather than the latter.)
Related
I'm making some exercise to practice my Haskell skills. My task is to implement the Haskell function find by myself with the filter function.
I already implemented the find function without the filter function (see codeblock below) but now my problem is to implement it with filter function.
-- This is the `find` function without `filter` and it's working for me.
find1 e (x:xs)= if e x then x
else find1 e xs
-- This is the find function with the filter function
find2 e xs = filter e xs
The result of find1 is right
*Main> find1(>4)[1..10]
Output : [5].
But my actual task to write the function with filter gives me the
*Main> find2(>4)[1..10]
Output : [5,6,7,8,9,10].
My wanted result for find2 is the result of find1.
To "cut a list" to only have one, head element in it, use take 1:
> take 1 [1..]
[1]
> take 1 []
[]
> take 1 $ find2 (> 4) [1..10]
[5]
> take 1 $ find2 (> 14) [1..10]
[]
If you need to implement your own take 1 function, just write down its equations according to every possible input case:
take1 [] = []
take1 (x:xs) = [x]
Or with filter,
findWithFilter p xs = take1 $ filter p xs
Your find1 definition doesn't correspond to the output you show. Rather, the following definition would:
find1 e (x:xs) = if e x then [x] -- you had `x`
else find1 e xs
find1 _ [] = [] -- the missing clause
It is customary to call your predicate p, not e, as a mnemonic device. It is highly advisable to add type signatures to all your top-level definitions.
If you have difficulty in writing it yourself you can start without the signature, then ask GHCi which type did it infer, than use that signature if it indeed expresses your intent -- otherwise it means you've coded something different:
> :t find1
find1 :: (t -> Bool) -> [t] -> [t]
This seems alright as a first attempt.
Except, you actually intended that there would never be more than 1 element in the output list: it's either [] or [x] for some x, never more than one.
The list [] type is too permissive here, so it is not a perfect fit.
Such a type does exist though. It is called Maybe: values of type Maybe t can be either Nothing or Just x for some x :: t (read: x has type t):
import Data.Maybe (listToMaybe)
find22 p xs = listToMaybe $ filter p xs
We didn't even have to take 1 here: the function listToMaybe :: [a] -> Maybe a (read: has a type of function with input in [a] and output in Maybe a) already takes at most one element from its input list, as the result type doesn't allow for more than one element -- it simply has no more room in it. Thus it expresses our intent correctly: at most one element is produced, if any:
> find22 (> 4) [1..10]
Just 5
> find22 (> 14) [1..10]
Nothing
Do add full signature above its definition, when you're sure it is what you need:
find22 :: (a -> Bool) -> [a] -> Maybe a
Next, implement listToMaybe yourself. To do this, just follow the types, and write equations enumerating the cases of possible input, producing an appropriate value of the output type in each case, just as we did with take1 above.
I am writing a small function in Haskell to check if a list is a palindrome by comparing it with it's reverse.
checkPalindrome :: [Eq a] -> Bool
checkPalindrome l = (l == reverse l)
where
reverse :: [a] -> [a]
reverse xs
| null xs = []
| otherwise = (last xs) : reverse newxs
where
before = (length xs) - 1
newxs = take before xs
I understand that I should use [Eq a] in the function definition because I use the equality operator later on, but I get this error when I compile:
Expected kind ‘*’, but ‘Eq a’ has kind ‘GHC.Prim.Constraint’
In the type signature for ‘checkPalindrome’:
checkPalindrome :: [Eq a] -> Bool
P.s Feel free to correct me if I am doing something wrong with my indentation, I'm very new to the language.
Unless Haskell adopted a new syntax, your type signature should be:
checkPalindrome :: Eq a => [a] -> Bool
Declare the constraint on the left hand side of a fat-arrow, then use it on the right hand side.
Unlike OO languages, Haskell makes a quite fundamental distinction between
Constraints – typeclasses like Eq.
Types – concrete types like Bool or lists of some type.
In OO languages, both of these would be represented by classes†, but a Haskell type class is completely different. You never have “values of class C”, only “types of class C”. (These concrete types may then contain values, but the classes don't.)
This distinction may seem pedantic, but it's actually very useful. What you wrote, [Eq a] -> Bool, would supposedly mean: each element of the list must be comparable... but comparable to what? You could have elements of different type in the list, how do you know that these elements are comparable to each other? In Haskell, that's no issue, because whenever the function is used you first settle on one type a. This type must be in the Eq class. The list then must have all elements from the same type a. This way you ensure that each element of the list is comparable to all of the others, not just, like, comparable to itself. Hence the signature
checkPalindrome :: Eq a => [a] -> Bool
This is the usual distinction on the syntax level: constraints must always‡ be written on the left of an => (implication arrow).
The constraints before the => are “implicit arguments”: you don't explicitly “pass Eq a to the function” when you call it, instead you just pass the stuff after the =>, i.e. in your example a list of some concrete type. The compiler will then look at the type and automatically look up its Eq typeclass instance (or raise a compile-time error if the type does not have such an instance). Hence,
GHCi, version 7.10.2: http://www.haskell.org/ghc/ :? for help
Prelude> let palin :: Eq a => [a] -> Bool; palin l = l==reverse l
Prelude> palin [1,2,3,2,1]
True
Prelude> palin [1,2,3,4,5]
False
Prelude> palin [sin, cos, tan]
<interactive>:5:1:
No instance for (Eq (a0 -> a0))
(maybe you haven't applied enough arguments to a function?)
arising from a use of ‘palin’
In the expression: palin [sin, cos, tan]
In an equation for ‘it’: it = palin [sin, cos, tan]
...because functions can't be equality-compared.
†Constraints may in OO also be interfaces / abstract base classes, which aren't “quite proper classes” but are still in many ways treated the same way as OO value-classes. Most modern OO languages now also support Haskell-style parametric polymorphism in addition to “element-wise”/covariant/existential polymorphism, but they require somewhat awkward extends trait-mechanisms because this was only implemented as an afterthought.
‡There are also functions which have “constraints in the arguments”, but that's a more advanced concept called rank-n polymorphism.
This is really an extended comment. Aside from your little type error, your function has another problem: it's extremely inefficient. The main problem is your definition of reverse.
reverse :: [a] -> [a]
reverse xs
| null xs = []
| otherwise = (last xs) : reverse newxs
where
before = (length xs) - 1
newxs = take before xs
last is O(n), where n is the length of the list. length is also O(n), where n is the length of the list. And take is O(k), where k is the length of the result. So your reverse will end up taking O(n^2) time. One fix is to just use the standard reverse function instead of writing your own. Another is to build up the result recursively, accumulating the result as you go:
reverse :: [a] -> [a]
reverse xs0 = go [] xs0
go acc [] = acc
go acc (x : xs) = go (x : acc) xs
This version is O(n).
There's another source of inefficiency in your implementation:
checkPalindrome l = (l == reverse l)
This isn't nearly as bad, but let's look at what it does. Suppose we have the string "abcdefedcba". Then we test whether "abcdefedcba" == "abcdefedcba". By the time we've checked half the list, we already know the answer. So we'd like to stop there! There are several ways to accomplish this. The simplest efficient one is probably to calculate the length of the list as part of the process of reversing it so we know how much we'll need to check:
reverseCount :: [a] -> (Int, [a])
reverseCount xs0 = go 0 [] xs0 where
go len acc [] = (len, acc)
go len acc (x : xs) = len `seq`
go (len + 1) (x : acc) xs
Don't worry about the len `seq` bit too much; that's just a bit of defensive programming to make sure laziness doesn't make things inefficient; it's probably not even necessary if optimizations are enabled. Now you can write a version of == that only looks at the first n elements of the lists:
eqTo :: Eq a => Int -> [a] -> [a] -> Bool
eqTo 0 _ _ = True
eqTo _ [] [] = True
eqTo n (x : xs) (y : ys) =
x == y && eqTo (n - 1) xs ys
eqTo _ _ _ = False
So now
isPalindrome xs = eqTo ((len + 1) `quot` 2) xs rev_xs
where
(len, rev_xs) = reverseCount xs
Here's another way, that's more efficient and arguably more elegant, but a bit tricky. We don't actually need to reverse the whole list; we only need to reverse half of it. This saves memory allocation. We can use a tortoise and hare trick:
splitReverse ::
[a] ->
( [a] -- the first half, reversed
, Maybe a -- the middle element
, [a] ) -- the second half, in order
splitReverse xs0 = go [] xs0 xs0 where
go front rear [] = (front, Nothing, rear)
go front (r : rs) [_] = (front, Just r, rs)
go front (r : rs) (_ : _ : xs) =
go (r : front) rs xs
Now
isPalindrome xs = front == rear
where
(front, _, rear) = splitReverse xs
Now for some numbers, using the test case
somePalindrome :: [Int]
somePalindrome = [1..10000] ++ [10000,9999..1]
Your original implementation takes 7.523s (2.316 mutator; 5.204 GC) and allocates 11 gigabytes to build the test list and check if it's a palindrome. My counting implementation takes less than 0.01s and allocates 2.3 megabytes. My tortoise and hare implementation takes less than 0.01s and allocates 1.7 megabytes.
I am a beginning student in Haskell. I have written a little csv file.
csv = ["a1","b1","c1","d1"]
["a2","b2","c2","d2"]
["a3","b3","c3","d3"]
I want to transfer to a graph par:
graph :: [(Str,Str,Str)]
graph :: [("a1","b","b1"),
("a1","b","c1")
("a1","b","d1")]
a::[[str]] -> [String,String,String]
f csv = ?
test = a csv == graph
Can you explain me how to do it?TKS
Edit: Oops, I missed the purpose of the special case. Fixed the answer...
Your program is almost correct, but unfortunately it won't type check. If you're using GHC, you'll get a terrifying error like the following:
Fsplit.hs:5:30: error:
• Couldn't match type ‘x’ with ‘[x]’
‘x’ is a rigid type variable bound by
the type signature for:
fsplit :: forall x. Eq x => Int -> [x] -> [[x]]
at Fsplit.hs:3:11
Expected type: [[x]]
Actual type: [x]
• In the expression: (l)
In the expression:
if n == 0 then (l) else (take n l) : (fsplit (m - 1) (drop n l))
In an equation for ‘fsplit’:
fsplit m l
= if n == 0 then (l) else (take n l) : (fsplit (m - 1) (drop n l))
where
n = div (length l) m
• Relevant bindings include
l :: [x] (bound at Fsplit.hs:5:10)
fsplit :: Int -> [x] -> [[x]] (bound at Fsplit.hs:4:1)
The important things to pick out of this error message are:
The error occurred at line 5, column 30 (which in my source file corresponds to the (l) after the then keyword)
Haskell expected the type [[x]] but encountered the actual type [x]
This happened when trying to type-check the expression (l)
Figuring this one out can be a little tricky when you're new to Haskell, but the problem is that you're trying to handle the special case where the original list l is shorter than the sublist size by returning the original list. However, the type of l is [x], a list of some type x, but your function returns a value of type [[x]], which is a list of lists of some type x.
This is a hint that you have a logic error in your program. In this special case (l too short), you don't really want to return the original list l, instead you want to return a list of sublists where the only sublist is the list l. That is, you want to return the singleton list [l]:
fsplit m l = if (n==0) then [l] else (take n l ):(fsplit (m-1)(drop n l))
where n = div (length l ) m
and that should work fine:
> fsplit 5 []
[]
> fsplit 5 [1..10]
[[1,2],[3,4],[5,6],[7,8],[9,10]]
> fsplit 3 [1..10]
[[1,2,3],[4,5,6],[7,8,9,10]]
> fsplit 20 [1..10]
[[1,2,3,4,5,6,7,8,9,10]]
Here is my code:
test :: (Num a) => [a] -> a
test [] = 0
test [x:xs] = x + test xs
Yet when I run it through ghci as :l test, I get this error:
[1 of 1] Compiling Main ( test.hs, interpreted )
test.hs:3:7:
Couldn't match type `a' with `[a]'
`a' is a rigid type variable bound by
the type signature for spew :: Num a => [a] -> a at test.hs:2:1
In the pattern: x : xs
In the pattern: [x : xs]
In an equation for `spew': spew [x : xs] = x + spew xs
Failed, modules loaded: none.
Try not to laugh :) it's my first attempt at haskell. Any help or explanations would be awesome.
PS: I know this could be easily done with a fold, but I'm trying to practice writing my own type signatures. Thanks in advance!!
You mean
test :: (Num a) => [a] -> a
test [] = 0
test (x:xs) = x + test xs -- note round brackets
with round brackets.
[x:xs] is a list with one element, itself a list, whereas (x:xs) is a list with a first element x and tail xs.
If you type length (1:[1,1,1]) you'll get 4, but if you type length [1:[1,1,1]] you'll get 1 - the only element is a list.
You probably meant to match the list as a whole, not the first element of the list:
test (x:xs) = ...
If you do otherwise, the pattern has the inferred type [[b]], so a == [b] according to tests signature, so xs must have type [b], so test xs must have type b but also type a according to the signature of test, which would mean that a == [a], which is a contradiction and leads to the unification error :)
I am working on a function in Haskell that will take one list and divide it into two evenly sized lists. Here is what I have:
split (x:y:xs) = split2 ([((length(x:y:xs) `div` 2)-2) : x ++ y] : [xs])
split2 (x:xs:[y:ys]) = split2 ((x-1) : [xs] ++ y : [ys])
split2 (0:xs:[y:ys]) = (xs:[y:ys])
The function takes the first two elements of a list, and puts them together into list #2 and appends the first list as a second element. It then gets the length of the list, and divides it by two to find out how many times to run taking into account the fact that it already removed two elements from the first list. It then takes those two pieces of information and puts it into split2, which takes another element from the first list and appends it to the second list in the first element, also it counts down 1 from the number of runs and then runs again.
Problem is, when I run it I get this:
Functions.hs:19:49:
Occurs check: cannot construct the infinite type: t0 = [t0]
In the first argument of `(:)', namely `(y)'
19 refers to line 2, the first split2 function. Not exactly sure how to go about fixing this error. Any ideas?
It's hard to know where to start...
Let's define functions from ever larger chunks of the expression in split2.
f1 (x:y:xs) = (length(x:y:xs) `div` 2)-2
f1 :: [a] -> Int
Ok, so the argument is a list of something, and it returns an Int
f2 (x:y:xs) = ((length(x:y:xs) `div` 2)-2) : x
f2 :: [[Int]] -> [Int]
Here, the length Int is being cons'd with x, so x must be [Int], so (x:y:xs) must be [[Int]]. We can also infer that y has the same type as x, and xs is a list of things of the same type; [[Int]]. So the x ++ y will also be [Int].
So, [xs] will have type [[[Int]]]. Now, we wrap the result in a list constructor, and cons it with [xs]:
f3 (x:y:xs) = [((length(x:y:xs) `div` 2)-2) : x ++ y] : [xs]
f3 :: [[Int]] -> [[[Int]]]
I'm guessing you didn't expect the argument to be a list of lists of lists of Ints.
Now, if we look at split2, the argument pattern (x:xs:[y:ys]) implies that it is of type:
split2 :: [[a]] -> b
x :: [a]
xs :: [a]
y :: a
ys :: [a]
The rhs of the first definition of split2 tries to construct a new list by concatenating (x-1) : [xs] and y : [ys]. However, if we substitute the types into the y : [ys], we find:
y : [ys] :: a : [[a]]
But since (:) :: a -> [a] -> [a], this means that [[a]] must be the same type as [a], or a must be a list of itself, which is not possible.
The (x-1) is also badly typed, because it attempts to subtract one from a list.
I can't tell if you want to split the lists into even and odd elements, or into first and second halves.
Here are two versions that split into the first and second halves, rounding down (RD) or up (RU) if the length is odd:
splitRD xs = splitAt (length xs `div` 2) xs
splitRU xs = splitAt ((length xs + 1) `div` 2) xs
Here's a version that splits the list into even and odd elements:
splitEO [] = ([], [])
splitEO [e] = ([e], [])
splitEO (e:o:xs) = (e:es, o:os) where (es, os) = splitEO xs
Few suggestions
Write types to all the functions. It makes the code more readable and also helps catching errors.
The type of ++ is [a] -> [a] -> [a] and you are adding length of a list along with elements. Since list has to be of uniform type and length returns Int type, so compiler infers type of split as
[[Int]] -> t (assuming split2 returns type t).
When you pass ([((length(x:y:xs)div2)-2) : x ++ y] : [xs]) to split2.
xs is of type [[Int]] which means
[xs] is of type [[[Int]]]
, so compiler infers type of split2 to [[[Int]]] -> t.
Now in the definition of split2
split2 (x:xs:[y:ys]) = split2 ((x-1) : [xs] ++ y : [ys])
ys is of type [[Int]], so y is of type [Int]. xs is of type [[Int]], but you are doing [xs] ++ y, which means both [xs] and y should be of same type ( [a] for some a).
Since you have not provided any types compiler is totally confused how to infer such type.
If you simply want to split the list into two equal parts why not do something more simpler like
split3 :: [a] -> ([a], [a])
split3 [] = ([],[])
split3 [x] = ([x],[])
split3 (x:y:xs) = let (xs',ys') = split3 xs in (x:xs',y:ys')
You seem to be passing state around in a list instead of as values to a function, which creates problems when it seems to the compiler as though you're creating a list of heterogenous values, whereas lists in Haskell are supposed to be of homogenous type.
Instead of
split2 (0:xs:[y:ys])
you should pass the different arguments/values to the function separately like this
split2 n xs (y:ys)
The functionality you're looking for is also reproduced in standard library functions.
halveList xs = splitAt (length xs `div` 2) xs
In Haskell, the elements of a list need to be all of the same type. In your function the lists contain a mixture of Ints, elements of the original list, and sublists of the original list, all of which are probably different types.
You also have some confusion about how to append lists and elements. x ++ y can only be used when x and y are themselves lists, while x : y can only be used when y is a list and x is an element of a list; to make a new list containing x and y as elements instead use [x, y] (although x:[y] also works). Similarly [xs] ++ y needs to be xs ++ [y] instead.
Without changing your basic algorithm, the simplest solution is probably to let split2 take 3 separate arguments.
split (x:y:xs) = split2 ((length(x:y:xs) `div` 2)-2) [x,y] xs
split2 n xs (y:ys) = split2 (n-1) (xs++[y]) ys
split2 0 xs ys = [xs,ys]