I got a Haskell function that is defined using pattern matching but i'm not really understand why is it looks like the way it is.
safeTail (x : xs) = xs
I'm not really understand specifically at the (x : xs), what does it mean ?
Consider a similar definition for a list data type.
data List a = Empty | Cons a (List a) -- (1)
There are two constructors: one to create an empty list, and another to create a list given a value and another list.
Pattern matching works by matching a value against the constructor used to create it.
safeTail (Cons x xs) = xs -- (2)
That is, if safeTail is applied to a value defined using the Cons constructor, then the return value is the second argument to Cons.
In real code, both the type constructor List and the Empty data constructor are named [] and the Cons constructor is named (:).
data [] a = [] | (:) a ([] a)
which Haskell allows to be written with special syntax
data [a] = [] | a : [a]
Applying the type constructer [] to a type or type variable can be replaced by including the argument inside the [], and the symbolic constructor (because it starts with a :) can be used as an infix operator.
That is, you could write
safeTail ((:) x xs) = xs -- (3)
or
safeTail (x : xs) = xs -- (4)
with (2), (3), and (4) being equivalent to (1) above.
>>> safeTail ((:) 3 ((:) 2 ((:) 1 [])))
[2,1]
>>> safeTail (3:2:1:[])
[2,1]
>>> safeTail [3,2,1]
[2,1]
For further simplicity, Haskell represents (x:[]) as [x], (x:y:[]) as [x,y], etc.
A complete definition of safeTail would also provide a value for an empty list argument:
safeTail [] = []
or a Maybe-based definition
safeTail :: [a] -> Maybe [a]
safeTail [] = Nothing
safeTail (x:xs) = Just xs
Thats the pattern matching.
The first argument to your function safeTail is some list type. In case the argument is a non-empty list, this pattern matching will succeed and bind the x to the head element and xs to the tail of the list.
In case you pass an empty list to safeTail the pattern match will fail and other patterns (if any exists) are checked.
Related
I don't understand the role of the colon in the following lambda expression:
myFunction :: [Int] -> [Int]
myFunction li = foldr (\x acc -> if x < 10 then x : acc else acc) [last li] li
I'm used to seeing the colon for recursive actions, however it looks like this colon is effectively saying prepend to current accumulator list, is that right?
: is a data constructor. It prepends a value of type a to an existing (possibly empty) list of type [a].
let x = 1 : [2,3,4] -- x == [1,2,3,4]
You can picture the list type constructor as being defined like this:
data [] a = [] | a : [] a -- : as an infix operator
data [] a = [] | (:) a ([] a) -- : in prefix positino
which might read more easily as
-- [] == List
-- (:) == Cons
data List a = EmptyList | Cons a (List a)
By "recursive action", I assume you mean you see it being used in a pattern matching situation like
head (a:as) = a
This is not unique to (:); pattern matching can be done with any data constructor.
I'm trying to match **String Newline String** pattern in a function Split.
split::String -> [String]
split[] = []
split (x++'\n':xs) = [x]++split(xs)
I'm getting this error:
Parse error in pattern: x ++ ('\n' : xs)
What am I doing wrong here?
I know there are other ways of achieving the same result but I'd like to understand what wrong with this pattern. I'm fairly new to Haskell BTW.
One problem (as I understand it) is that ++ is not a constructor of the list data type the way : is. You can think of the list data type being defined as
data [a] = [] | a : [a]
Where : is a constructor that appends elements to the front of a list. However, ++ is a function (defined in the documentation here: http://hackage.haskell.org/package/base-4.8.1.0/docs/src/GHC.Base.html#%2B%2B) as
(++) :: [a] -> [a] -> [a]
(++) [] ys = ys
(++) (x:xs) ys = x : xs ++ ys
We could define our own data type list like
data List a = Empty | Cons a (List a)
That would mimic the behavior of our familiar list. In fact, you could use (Cons val) in a pattern. I believe you could also define a type with a concat constructor like so
data CList a = Empty | Cons a (CList a) | Concat (CList a) (CList a)
Which you could use to lazily concatenate two lists and defer joining them into one. With such a data type you could pattern match against the Concat xs ys input, but you that would only work on the boundary of two lists and not in the middle of one.
Anyway I'm still fairly new to Haskell myself but I hope this is on point.
Imagine you could. Then matching "a\nb\nc" could produce x = "a", xs = "b\nc" or x = "a\nb", xs = "c" and you'd need some ad hoc rule to decide which to use. Matching against functions is also impossible to reasonably implement in general: you need to find an x given f x, and there is no way to do this other than trying all possible x.
I'm new to haskell.
I wrote a simple code.
But it does not work.
I'm getting this 'can not construct infinite type' error.
How does it fix.
reverse' list
| null list = []
| otherwise = (reverse' (tail list)) : (head list)
The problem arises from your use of the : operator, which has the type
(:) :: a -> [a] -> [a]
So it takes an element and a list, and returns a new list with that element prepended on. Where you have
reverse' (tail list) : head list
-- parentheses removed since they're not needed
the type of reverse' (tail list) is [a], and the type of head list is a, so the compiler tries to make it so that a ~ [a], which obviously can't work. Instead, you can use the ++ operator and put head list into a list itself:
reverse' (tail list) ++ [head list]
But keep in mind that this is not a very efficient solution, concatenation onto the end of Haskell lists is slow since they're singly linked lists.
I just started using Haskell and wanted to write a function that, given a list, returns a list in which every 2nd element has been doubled.
So far I've come up with this:
double_2nd :: [Int] -> [Int]
double_2nd [] = []
double_2nd (x:xs) = x : (2 * head xs) : double_2nd (tail xs)
Which works but I was wondering how you guys would write that function. Is there a more common/better way or does this look about right?
That's not bad, modulo the fixes suggested. Once you get more familiar with the base library you'll likely avoid explicit recursion in favor of some higher level functions, for example, you could create a list of functions where every other one is *2 and apply (zip) that list of functions to your list of numbers:
double = zipWith ($) (cycle [id,(*2)])
You can avoid "empty list" exceptions with some smart pattern matching.
double2nd (x:y:xs) = x : 2 * y : double2nd xs
double2nd a = a
this is simply syntax sugar for the following
double2nd xss = case xss of
x:y:xs -> x : 2 * y : double2nd xs
a -> a
the pattern matching is done in order, so xs will be matched against the pattern x:y:xs first. Then if that fails, the catch-all pattern a will succeed.
A little bit of necromancy, but I think that this method worked out very well for me and want to share:
double2nd n = zipWith (*) n (cycle [1,2])
zipWith takes a function and then applies that function across matching items in two lists (first item to first item, second item to second item, etc). The function is multiplication, and the zipped list is an endless cycle of 1s and 2s. zipWith (and all the zip variants) stops at the end of the shorter list.
Try it on an odd-length list:
Prelude> double_2nd [1]
[1,*** Exception: Prelude.head: empty list
And you can see the problem with your code. The 'head' and 'tail' are never a good idea.
For odd-lists or double_2nd [x] you can always add
double_2nd (x:xs) | length xs == 0 = [x]
| otherwise = x : (2 * head xs) : double_2nd (tail xs)
Thanks.
Here's a foldr-based solution.
bar :: Num a => [a] -> [a]
bar xs = foldr (\ x r f g -> f x (r g f))
(\ _ _ -> [])
xs
(:)
((:) . (*2))
Testing:
> bar [1..9]
[1,4,3,8,5,12,7,16,9]
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]