split :: [a] -> Int -> ([a], [a])
split [xs] n =
(take n [xs], drop n [xs])
The same code works if I give the variable as xs instead of [xs], signatures are same in both cases. Using [xs] gives the error that pattern is non-exhaustive. I understand it's telling that the input I gave is not covered by my code, but not clear what is happening under the hood.
Test input: [1,2,3] 2.
Somehow a lot of people think that [xs] as pattern means that you unify a list with xs. But this is incorrect, since the function signature (either derived implicitly, or stated explicitly) already will prevent you to write code where you call the function with a non-list item.
A list has two constructors:
the empty list []; and
the "cons" (h : t) with h the head (first element), and t the tail (a list with the remaining elements).
Haskell however introduces some syntactical sugar as well. For example [1] is short for (1:[]), and [1, 4, 2] for (1:(4:(2:[]))).
So that means that if you write [xs], behind the curtains you defined a pattern (xs: []) which thus means you match all lists with exactly one element, and that single element (not the entire list) is then xs.
Anyway, the solution is to use:
split xs n = (take n xs, drop n xs)
Since both take :: Int -> [a] -> [a] and drop :: Int -> [a] -> [a] have in the signature that xs is supposed to be a list, Haskell will derive automatically that n is supposed to be an Int, and xs an [a].
Note that you can use splitAt :: Int -> [a] -> ([a], [a]) as well. We can make the signature equivalent to the one you target with:
split = flip splitAt
Related
I have two functions computing the length of a list of integers
lengthFoldl :: [Int] -> Int
lengthFoldl xs = (foldl (\_ y -> y+1) 0 xs)
and
lengthFold :: [a] -> Int
lengthFold xs = foldr (\_ y -> y+1) 0 xs
they are the same except one uses foldr and one foldl.
But when trying to compute the length of any list [1 .. n] I get a wrong result (one too big) from lengthFoldl.
To complement joelfischerr's answer, I'd like to point out that a hint is given by the types of your functions.
lengthFoldl :: [Int] -> Int
lengthFold :: [a] -> Int
Why are they different? I guess you might had to change the first one to take an [Int] since with [a] it did not compile. This is however a big warning sign!
If it is indeed computing the length, why should lengthFoldl care about what is the type of the list elements? Why do we need the elements to be Ints? There is only one possible explanation for Int being needed: looking at the code
lengthFoldl xs = foldl (\_ y -> y+1) 0 xs
we can see that the only numeric variable here is y. If y is forced to be a number, and list elements are also forced to be numbers, it seems as if y is taken to be a list element!
And indeed that is the case: foldl passes to the function the accumulator first, the list element second, unlike foldr.
The general thumb rule is: when type and code do not agree, one should think carefully about which one is right. I'd say that most Haskellers would think that, in most cases, it is easier to get the type right than the code right. So, one should not just adapt the type to the code to force it to compile: a type error can instead witness a bug in the code.
Looking at the type definitions of foldl and foldr it becomes clear what the issue is.
:t foldr
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
and
:t foldl
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b
One can see that the foldr takes the item of the list and the second argument into the function and foldl takes the second argument and the item of the list into the function.
Changing lengthFoldl to this solves the problem
lengthFoldl :: [Int] -> Int
lengthFoldl xs = foldl (\y _ -> y+1) 0 xs
Edit: Using foldl instead of foldl' is a bad idea: https://wiki.haskell.org/Foldr_Foldl_Foldl'
split :: [a] -> Int -> ([a], [a])
split [xs] n =
(take n [xs], drop n [xs])
The same code works if I give the variable as xs instead of [xs], signatures are same in both cases. Using [xs] gives the error that pattern is non-exhaustive. I understand it's telling that the input I gave is not covered by my code, but not clear what is happening under the hood.
Test input: [1,2,3] 2.
Somehow a lot of people think that [xs] as pattern means that you unify a list with xs. But this is incorrect, since the function signature (either derived implicitly, or stated explicitly) already will prevent you to write code where you call the function with a non-list item.
A list has two constructors:
the empty list []; and
the "cons" (h : t) with h the head (first element), and t the tail (a list with the remaining elements).
Haskell however introduces some syntactical sugar as well. For example [1] is short for (1:[]), and [1, 4, 2] for (1:(4:(2:[]))).
So that means that if you write [xs], behind the curtains you defined a pattern (xs: []) which thus means you match all lists with exactly one element, and that single element (not the entire list) is then xs.
Anyway, the solution is to use:
split xs n = (take n xs, drop n xs)
Since both take :: Int -> [a] -> [a] and drop :: Int -> [a] -> [a] have in the signature that xs is supposed to be a list, Haskell will derive automatically that n is supposed to be an Int, and xs an [a].
Note that you can use splitAt :: Int -> [a] -> ([a], [a]) as well. We can make the signature equivalent to the one you target with:
split = flip splitAt
I try to learn Haskell and I don't know how to create a function which takes a list of lists and multiplies each element in this list e.g.
[[2,3], [8,3,2], [2,10,1], [2,2,2,2]] -> [6,48,20,16]
I try something like this but it doesn't work. If anyone knows how to do this will be really helpfully for me:
listOfProductInt :: [[Int]] -> [Int]
listOfProductInt [] = []
listOfProductInt lists = foldl (\y x-> multipleInts x concat) [] lists
multipleInts :: (Num a) => [a] -> a
multipleInts list1 = foldl (\y x -> y * x) 1 list1
Very simple really, you need map:
map product [[2,3],[8,3,2],[2,10,1],[2,2,2,2]]
The product function multiplies all elements in a list. It is included in the Prelude, which is imported by default. In other words, it is normally available.
The map function applies that function to each element in the list.
If you prefer a solution with folds only, first a couple of rules of thumb:
Never use foldl (“lazy† left fold”), except in very specific circumstances (which you won't encounter until you've long learned the subtleties).
Use foldr (lazy right fold) for deconstructing lists, if the result is lazy. In particular, this is usually the right choice if your fold produces a list again: foldr will only consume the list by demand, and it doesn't keep a reference to the original head, hence it works smoothly even on infinite lists and avoids memory blowup (in fact, the garbage collector can reclaim parts of the list that are already processed, before the processing is finished!)
Use foldl' (strict left fold) for “atomic” operations like computing the sum of all values in a list.
So let's start with
listOfProductInt :: [[Int]] -> [Int]
-- listOfProductInt [] = [] -- no need for that, folds already handle the empty case.
listOfProductInt lists = foldr _ [] lists
multipleInts :: (Num a) => [a] -> a
multipleInts list1 = foldl' _ 1 list1
GHC will inform you
/tmp/wtmpf-file9164.hs:4:32:
Found hole ‘_’ with type: [Int] -> [Int] -> [Int]
Relevant bindings include
lists :: [[Int]] (bound at /tmp/wtmpf-file9164.hs:4:18)
listOfProductInt :: [[Int]] -> [Int]
(bound at /tmp/wtmpf-file9164.hs:4:1)
In the first argument of ‘foldr’, namely ‘_’
Unfortunately this is not as informtive as usually because both the result and the individual sub-lists have type [Int]. I'll annotate the type:
[Int] -- the sublist we're focusing on
-> [Int] -- the result of the future product-computations yet to be done
-> [Int] -- the result at this point of the computation
Now, for handling the sublist that's on the agenda first, we have multipleInts. So, it should look something like
listOfProductInt lists = foldr (\l -> _ (multipleInts l)) [] lists
to which GHC replies
/tmp/wtmpf-file9164.hs:4:39:
Found hole ‘_’ with type: Int -> [Int] -> [Int]
Relevant bindings include
l :: [Int] (bound at /tmp/wtmpf-file9164.hs:4:34)
lists :: [[Int]] (bound at /tmp/wtmpf-file9164.hs:4:18)
listOfProductInt :: [[Int]] -> [Int]
(bound at /tmp/wtmpf-file9164.hs:4:1)
In the expression: _
In the expression: _ (multipleInts l)
In the first argument of ‘foldr’, namely
‘(\ l -> _ (multipleInts l))’
You may recognise Int -> [Int] -> [Int], or generally a -> [a] -> [a], as the signature of the cons-operator (:), and that's what's needed here:
listOfProductInt lists = foldr (\l -> (:) (multipleInts l)) [] lists
or, using point-free composition,
listOfProductInt = foldr ((:) . multipleInts) []
Proceed with the implementation of multipleInts:
/tmp/wtmpf-file9164.hs:7:29:
Found hole ‘_’ with type: a -> a -> a
Where: ‘a’ is a rigid type variable bound by
the type signature for multipleInts :: Num a => [a] -> a
at /tmp/wtmpf-file9164.hs:6:17
Relevant bindings include
list1 :: [a] (bound at /tmp/wtmpf-file9164.hs:7:14)
Well, a -> a -> a where a fulfills a Num constraint? That's just the simple product operation!
multipleInts list1 = foldl' (*) 1 list1
†foldl is only lazy in the values, but not in the spine. In practice, this tends to give you the worst of both worlds: the processor is immediately clogged with having to handle the whole list, but instead of actually doing useful computations, it merely builds up stacks of memory-hogging laziness-thunks.
I am wondering why :sprint reports xs = _ in this case:
Prelude> xs = map (+1) [1..10]
Prelude> length xs
10
Prelude> :sprint xs
xs = _
but not in this case:
Prelude> xs = map (+1) [1..10] :: [Int]
Prelude> length xs
10
Prelude> :sprint xs
xs = [_,_,_,_,_,_,_,_,_,_]
Note: I am running ghci with -XNoMonomorphismRestriction. Does it have to do with the fact that the type of xs is polymorphic in the first case but not in the second? I'd like to know what's going on internally.
The gist is that the with the polymorphic xs it has a type of the form
xs :: Num a => [a]
typeclasses under the hood are really just functions, they take an extra argument that GHC automatically fills that contains a record of the typeclasses functions. So you can think of xs having the type
xs :: NumDict a -> [a]
So when you run
Prelude> length xs
It has to choose some value for a, and find the corresponding NumDict value. IIRC it'll fill it with Integer, so you're actually calling a function with and checking the length of the resulting list.
When you then :sprint xs, you once again fill in that argument, this time with a fresh type variable. But the point is that you're getting an entirely different list, you gave it a different NumDict so it's not forced in any way when you called length before.
This is very different then with the explicitly monomorphic list since there really is only one list there, there's only one value to force so when you call length, it forces it for all future uses of xs.
To make this a bit clearer, consider the code
data Smash a = Smash { smash :: a -> a -> a }
-- ^ Think of Monoids
intSmash :: Smash Int
intSmash = Smash (+)
listSmash :: Smash [a]
listPlus = Smash (++)
join :: Smash a -> [a] -> a
join (Smash s) xs = foldl1' s xs
This is really what type classes are like under the hood, GHC would automatically fill in that first Smash a argument for us. Now your first example is like join, we can't make any assumptions about what the output will be as we apply it to different types, but your second example is more like
join' :: [Int] -> Int
join' = join intSmash
The code below retains, for a given integer n, the first n items from a list, drops the following n items, keeps the following n and so on. It works correctly for any finite list.
In order to make it usable with infinite lists, I used the 'seq' operator to force the accumulator evaluation before the recursive step as in foldl' as example.
I tested by tracing the accumulator's value and it seems that it is effectively computed as desired with finite lists.
Nevertheless, it doesn't work when applied to an infinite list. The "take" in the main function is only executed once the inner calculation is terminated, what, of course, never happens with an infinite list.
Please, can someone tell me where is my mistake?
main :: IO ()
main = print (take 2 (foo 2 [1..100]))
foo :: Show a => Int -> [a] -> [a]
foo l lst = inFoo keepOrNot 1 l lst []
inFoo :: Show a => (Bool -> Int -> [a] -> [a] -> [a]) -> Int -> Int -> [a] -> [a] -> [a]
inFoo keepOrNot i l [] lstOut = lstOut
inFoo keepOrNot i l lstIn lstOut = let lstOut2 = (keepOrNot (odd i) l lstIn lstOut) in
stOut2 `seq` (inFoo keepOrNot (i+1) l (drop l lstIn) lstOut2)
keepOrNot :: Bool -> Int -> [a] -> [a] -> [a]
keepOrNot b n lst1 lst2 = case b of
True -> lst2 ++ (take n lst1)
False -> lst2
Here's how list concatenation is implemented:
(++) :: [a] -> [a] -> [a]
(++) [] ys = ys
(++) (x:xs) ys = x : xs ++ ys
Note that
the right hand list structure is reused as is (even if it's not been evaluated yet, so lazily)
the left hand list structure is rewritten (copied)
This means that if you're using ++ to build up a list, you want the accumulator to be on the right hand side. (For finite lists, merely for efficiency reasons --- if the accumulator is on the left hand side, it will be repeatedly copied and this is inefficient. For infinite lists, the caller can't look at the first element of the result until it's been copied for the last time, and there won't be a last time because there's always something else to concatenate onto the right of the accumulator.)
The True case of keepOrNot has the accumulator on the left of the ++. You need to use a different data structure.
The usual idiom in this case is to use difference lists. Instead of using type [a] for your accumulator, use [a] -> [a]. Your accumulator is now a function that prepends a list to the list it's given as input. This avoids repeated copying, and the list can be built lazily.
keepOrNot :: Bool -> Int -> [a] -> ([a] -> [a]) -> ([a] -> [a])
keepOrNot b n lst1 acc = case b of
True -> acc . (take n lst1 ++)
False -> acc
The initial value of the accumulator should be id. When you want to convert it to a conventional list, call it with [] (i.e., acc []).
seq is a red herring here. seq does not force the entire list. seq only determines whether it is of the form [] or x : xs.
You're learning Haskell, yes? So it would be a good idea as an exercise to modify your code to use a difference list accumulator. Possibly the use of infinite lists will burn you in a different part of your code; I don't know.
But there is a better approach to writing foo.
foo c xs = map snd . filter fst . zipWith f [0..] $ xs
where f i x = (even (i `div` c), x)
So you want to group a list into groups of n elements, and drop every other group. We can write this down directly:
import Data.List (unfoldr)
groups n xs = takeWhile (not.null) $ unfoldr (Just . splitAt n) xs
foo c xs = concatMap head . groups 2 . groups c $ xs
dave4420 already explained what is wrong with your code, but I'd like to comment on how you got there, IMO. Your keepOrNot :: Bool -> Int -> [a] -> [a] -> [a] function is too general. It works according to the received Bool, any Bool; but you know that you will feed it a succession of alternating True and False values. Programming with functions is like plugging a pipe into a funnel - output of one function serves as input to the next - and the funnel is too wide here, so the contact is loose.
A minimal re-write of your code along these lines could be
foo n lst = go lst
where
go lst = let (a,b) = splitAt n lst
(c,d) = splitAt n b
in
a ++ go d
The contact is "tight", there's no "information leakage" here. We just do the work twice (*) ourselves, and "connect the pipes" explicitly, in this code, grabbing one result (a) and dropping the other (c).
--
(*) twice, reflecting the two Boolean values, True and False, alternating in a simple fashion one after another. Thus this is captured frozen in the code's structure, not hanging loose as a parameter able to accommodate an arbitrary Boolean value.
Like dava4420 said, you shouldn't be using (++) to accumulate from the left. But perhaps you shouldn't be accumulating at all! In Haskell, lazyness makes straighforward "head-construction" often more efficient than the tail recursions you'd need to use in e.g. Lisp. For example:
foo :: Int -> [a] -> [a] -- why would you give this a Show constraint?
foo ℓ = foo' True
where foo' _ [] = []
foo' keep lst
| keep = firstℓ ++ foo' False other
| otherwise = foo' True other
where (firstℓ, other) = splitAt ℓ lst