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]]
Related
I'm trying to make it so that on a tuple input (n,m) and a list of tuples xs , if the first item in the tuple in xs is in (n,m) then keep it that way in the new list otherwise add the a tuple consisting of some value k from n to m as a first element and as second element it should be 0.My question is:how can i say "repeat 0" using guards ? Since clearly my code won't run since my code says "repeat = 0"
expand :: (Int,Int) -> Profile ->Profile
expand (n,m) [] = zip [n..m] (repeat 0)
expand (n,m) (x:xs) = zip [n..m] (repeat (|(fst (x) `elem` [n..m]) == False = 0
|otherwise = snd (x))
You can use a helper function here that converts a number in the [ n .. m ] range to a 2-tuple. Here we thus try to find an element in the list xs that matches with the first item of that tuple, if we do not find such element, we use 0:
import Data.List(find)
expand :: (Int,Int) -> Profile -> Profile
expand (n,m) xs = map go [n .. m]
where go i | Just l <- find (\(f, _) -> f == i) xs = l
| otherwise = (i, 0)
For a list, find was implemented as [src]:
find :: (a -> Bool) -> [a] -> Maybe a
find p = listToMaybe . filter p
filter thus will make a list that contains the elements that satisfy the predicate p, and listToMaybe :: [a] -> Maybe a will convert an empty list [] to Nothing, and for a non-empty list (x:_) it will wrap the first element x in a Just data constructor. Due to Haskell's laziness, it will thus look for the first element that satisfies the predicate.
this thus gives us:
Prelude Data.List> expand (2,7) [(4, 2.3), (6, 3)]
[(2,0.0),(3,0.0),(4,2.3),(5,0.0),(6,3.0),(7,0.0)]
I am trying to implement a list-splitter based on a given predicate.The functionality is a similar to a recursive break.I input in a list ,and i append elements to a small list as long as the predicate for the given element is true.When the predicate is false i append the formed list to a bigger list and i continue from where i remained ignoring the element corresponding to the false predicate.
P.S: I am trying to not use any Data.List functions only self-implemented.(I'm in learning phase).
Example:
input
predicate: (\x->x<3)
list : [1,2,3,2,3,1,1,1,3]
output: [[1,2],[2],[1,1,1]]
I have tried so far with the following approach:
I use a list that given a list it breaks it in a tuple of 2.The first element is the list until the false predicate.The second is the rest.I feed this tuple to a function that performs this again and again.
splt::(a->Bool)->[a]->[[a]]
splt p []=[]
splt p (x:xs)=go p [] (x:xs) where
go p rez []=rez
go p rez ls=rez:process . brk $ ls [] where
process (x,[])=rez:x
process ([],x)=go p rez x
brk::(a->Bool)->[a]-> ([a],[a])
brk p []= ([],[])
brk p (x:xs)=go p ([],x:xs) where
go p (accu,[])= (accu,[])
go p (accu,x:xs)|not (p x) =(accu,xs)
|otherwise = go p (x:accu,xs)
I get the following error : cannot produce infinite type.
I have also tried a simpler solution:
format::(a->Bool)->[a]->[[a]]
format p []=[]
format p ls=go p [] [] ls where
go p small big []=small:big
go p small big (x:xs)=case p x of
True ->go p x:small big xs
False ->go p [] small:big xs
But it does not work and i also have to reverse the results in both cases.The error i get is:
* Couldn't match type `a' with `[a0]'
`a' is a rigid type variable bound by
the type signature for:
wrds :: forall a. (a -> Bool) -> [a] -> [[a]]
at Ex84.hs:12:5-31
Expected type: [a0] -> Bool
Actual type: a -> Bool
* In the first argument of `go', namely `p'
In the expression: go p [] []
ls
The second one is just a bracketing issue and can be remedied by correctly parenthesising the arguments as follows:
case p x of
True ->go p (x:small) big xs
False ->go p [] (small:big) xs
By not doing so, the lists are being treated as functions. You will have to map reverse on the resulting list as well in this case.
You can also try using the span function for this:
splt :: (a -> Bool) -> [a] -> [[a]]
splt _ [] = []
splt p xs = let (xs', xs'') = span p xs
remaining = dropWhile (not . p) xs''
in case xs' of
[] -> splt p remaining
xs' -> xs' : splt p xs''
This is a way of implementing what you need.
What I did is to use the function span, that breaks the list in two, returning a tuple. The first element is the list of initial elements satisfying p. The second element of the tuple is the remainder of the list.
I used this recursively, while discarding the elements that do not satisfy p.
splt :: (a -> Bool) -> [a] -> [[a]]
splt p [] = []
splt p ls = let (a,rs) = span p ls
(b,rs') = span (not . p) rs
in if null a then splt p rs' else a : splt p rs'
You can also try to define span yourself
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.)
I have to make a 2D list [[Int]]. out of a 1D list [Int] in Haskell.
The function should take to args "r" Int indicates the count of rows and a 1D list, which should be sliced into rows with the length of "r".
If length of the list is longer than r*r then the rest of the list should be dropped.
Howerver
If length of the list is shorter than r*r then the missing elements should be inserted in the list as 0.
Example 1:
Input:
r = 2
list = [1,2,3,4,5,6]
Output: [[1,2], [3,4]]
Example 2:
Input:
r = 3
list = [1,2,3,4,5,6]
Output: [[1,2,3], [4,5,6], [0,0,0]]
So my approach is over thre functions as follow:
zeroList :: Int -> [Int] -> [Int]
zeroList r myList = (take (r*r-(length myList)) (0 : zeroList r myList))
processList :: Int -> [Int] -> [[Int]]
processList r myList = (if (length myList < r*r)
then (myList:(zeroList r myList))
else if (length (myList > r*r))
then (reverse (drop r (reverse myList)))
else
myList)
make2DList :: Int -> [Int] -> [[Int]]
make2DList r myList = (if myList == []
then make2DList
else ( ( take r (processList r myList) ):( make2DList r ( drop r (processList r myList) ) )))
The zeroList function works properly but the other two functions don't work. I some compiling error messages:
D:\haskell\task1.hs:6:63:
Couldn't match expected type `[Int]' with actual type `Int'
Expected type: [[Int]]
Actual type: [Int]
In the return type of a call of `zeroList'
In the second argument of `(:)', namely `(zeroList r myList)'
D:\haskell\task1.hs:14:54:
Couldn't match expected type `[[Int]]'
with actual type `Int -> [Int] -> [[Int]]'
In the expression: make2DList
In the expression:
(if myList == [] then
make2DList
else
((take r myList) : (make2DList r (drop r myList))))
In an equation for `make2DList':
make2DList r myList
= (if myList == [] then
make2DList
else
((take r myList) : (make2DList r (drop r myList))))
Failed, modules loaded: none.
Prelude>
I can't comprehend, why it doesn't work although zeroList r myList. returns an ordinary list.
Could anyone help me please?
I have to admit that I don’t comprehend how you are trying to do it. All this if then else is quite unHaskellish. :-) Also, due to Haskell’s lazy evaluation and infinite lists, it is unnecessary to compute the exact number of needed zeroes etc. beforehand.
A rough draft how it could be done instead:
make2DList r l = take r . chunks r $ l ++ zeroes
where
zeroes = [0,0..]
chunks r xs = take r xs : chunks r (drop r xs)
Explanation:
Extend the list by an infinite number of zeroes so we don’t have to worry about padding anymore.
Make a chunks function that splits any list into chunks of the given length.
Apply chunks to the padded list.
Take as many rows as we need.
I can explain both of the compilation errors, and I have a question for you. I'll take the errors in reverse order.
Error at 14:54
First I'll explain how arguments are applied to functions in Haskell.
The function make2DList has type Int -> [Int] -> [[Int]], which is equivalent to Int -> ( [Int] -> [[Int]] ). This means that, if given one argument r (which must be of type Int) it returns a function of type [Int] -> [[Int]]. This returned function, if given an argument myList (which must be of type [Int]) returns a list of type [[Int]].
This means that the code make2DList r myList is equivalent to (make2DList r) myList. In any case, it must return a value of type [[Int]], that is, a list of lists of Ints.
But you have said that, in the event that myList is empty, it should return just make2DList. Unfortunately make2DList is a function of type Int -> [Int] -> [[Int]] and not a list of lists of type [[Int]], hence the compiler error message
Couldn't match expected type `[[Int]]'
with actual type `Int -> [Int] -> [[Int]]'
The fix is to supply some arguments to this call to make2DList. But do not supply an empty list as the second argument, or you will create an infinite loop. Probably what you actually want to do is to return an empty list of lists, written the same way as an empty list of anything: []
Edit: I should perhaps also explain how if ... then ... else works in Haskell. This is not at all like the if/then/else in imperative languages, and is actually just like the ternary operator. That is,
if a then b else c
in Haskell is, as far as I can tell, exactly the same as
a ? b : c
in another language.
Thus, in order for the whole expression (if a then b else c) to be of the right type, both b and c must be of the right type (and a must be boolean, of course). In your case, the whole if/then/else expression should be of type [[Int]] but your b is the expression make2DList (with no arguments), which is of course a function and not a list of lists as it should be.
Error at 6:63
The type of : is given by (:) :: a -> [a] -> [a]. This means that if whatever is on the left of the : has type a (for some a), then whatever is on the right should have type [a].
That is to say, whatever appears to the left of : will become the first element in the resulting list, and whatever is on the right of : will become the rest of the list, which means that the type of the rest of the list must be a list of the type of whatever the first element is.
Your first element is myList, which has type [Int], and what you're trying to use for the rest of the list is (zeroList r myList), which also has type [Int] and is thus only good as a single element.
Possible fixes (which would compile, but may or may not be correct) could include:
enclosing zeroList r myList in square brackets, thus:
myList:[zeroList r myList]
which would always create a list of two elements, each of which would be a list of Ints
concatenating the two lists, thus:
myList ++ (zeroList r myList)
but this would produce the wrong return type, so you'd have to put the result in another list. The following would compile, but is almost certainly not what you want:
[myList ++ (zeroList r myList)]
That r probably wants to be something like r - (length myList) or something too.
Question
I'm having trouble guessing how your functions are supposed to work. What are each of the two functions processList and make2DList supposed to do? I see that they both have the same type, so what is the difference?
import Data.List (replicate)
takeElse :: Int -> a -> [a] -> [a]
takeElse 0 _ _ = []
takeElse n alt [] = replicate n alt
takeElse n alt (x : xs) = x : takeElse (n - 1) alt xs
exotic :: Int -> a -> [a] -> [[a]]
exotic dum alt lst = exot dim lst
where
exot 0 _ = []
exot n xs = takeElse dim alt xs : exot (n - 1) (drop dim xs)
such that
exotic 3 0 [1,2,3,4] == [[1,2,3],[4,0,0],[0,0,0]]
exotic 1 ' ' "Hello" == ["H"]
exotic 4 ' ' "Hello" == ["Hell","o "," "," "]
takeElse 10 ' ' "Hello" == "Hello "
I am new to Haskell, and programming in general. I am trying to define a function which generates the sequence of Collatz numbers from n. I have:
collatz n = (collatz' n) : 1
where collatz' n = (takeWhile (>1) (collatz'' n))
where collatz'' n = n : collatz'' (collatz''' n)
where collatz''' 1 = 1
collatz''' n = if (even n) then (div n 2) else ((3*2)+1)
When I run this in GHCi, I get the error:
No instance for (Num [t])
arising from the literal `2' at <interactive>:1:7
Possible fix: add an instance declaration for (Num [t])
I don't know what this means. The problem seems to be appending "1" to the list. This problem emerges because
collatz' n = (takeWhile (>0) (collatz'' n))
generates an infinite sequence of "1"s following the correct Collatz sequence; however,
collatz' n = (takeWhile (>1) (collatz'' n))
generates all Collatz numbers from n except "1". What am I doing wrong?
(:) :: a -> [a] -> [a]
Your first line collatz n = (collatz' n) : 1 forces 1 to become [a].
I guess you wanted something like (collatz' n) ++ [1]
And you have error in if (even n) then (div n 2) else ((3*2)+1) there should be ((3*n)+1 or something like that else you have collatz''' 7 = 7
ony's answer is correct, but since you're new to Haskell, maybe this is a clearer explanation. The : operator prepends a value to a list, so doing somelist : 7 is invalid since that's trying to append a value to a list. That's why (collatz' n) : 1 doesn't compile, since the type of (collatz' n) is a list of numbers.
Try replacing the : 1 with ++ [1].
Another way to go at the problem may be for you to use a Data.Sequence structure instead of a list. Sequences allow you to "snoc" a value (put a value on the back of a sequence) as well as the more usual "cons" (put it on the front of the sequence).
Another solution for you may be to use span to make your own "takeUntil" function.
Let me explain: span p xs gives you the same answer as (takeWhile p xs, dropWhile p xs) for whichever p function and xs list you'd use, the same way that splitAt n xs is the same as (take n xs, drop n xs).
Anyway, you can use span to make your own "takeUntil" function:
takeUntil p xs = taken ++ take 1 dropped where
(taken, dropped) = span p xs
This is the form that you were looking for, when you used the collatz n = (collatz' n) : 1 form.
I hope this helps.