Related
This question already has answers here:
What is the equivalent to (+1) for the subtraction, since (-1) is seen as a negative number? [duplicate]
(3 answers)
Closed 1 year ago.
What was wrong with the following code?
map (+1) [1, 2, 3 ] == map (\x -> x + 1) [1, 2, 3]
map (1+) [1, 2, 3] == map (\x -> 1 + x) [1, 2, 3]
map (-1) [1, 2, 3] == map (\x -> x - 1) [1, 2, 3]
map (1-) [1, 2, 3] == map (\x -> 1 - x) [1, 2, 3]
Why the following does not work?
map (-1) [1, 2, 3]
(-1) is interpreted as a number: minus one. You can use subtract :: Num a => a -> a -> a to subtract a value:
map (subtract 1) [1, 2, 3] == map (\x -> x - 1) [1, 2, 3]
How can I make a function that groups element of a list into lists of predefined length without using explicit recursion.
For example, for 2:
[1, 2, 3, 4, 5, 6, 7, 8]
[[1, 2], [3, 4], [5, 6], [7, 8]]
Thank you!
The following would work (though you may consider it cheating to use groupBy from Data.List)
import Data.Function (on)
import Data.List (groupBy)
group :: Int -> [a] -> [[a]]
group n = map (map snd)
. groupBy ((==) `on` fst)
. zip (enumFrom 1 >>= replicate n)
This is a one-liner if you set your wrap at 100 characters :). I'm guessing you are looking for something that uses a fold.
group :: Int -> [a] -> [[a]]
group n = uncurry (:) . foldr (\x (l,r) -> if length l == n then ([x],l:r)
else (x:l,r))
([],[])
Given:
Prelude>[ [Just 10, Just 20], [Just 5] ]
[ [Just 10, Just 20], [Just 5] ]
it has type:
Prelude> :t [ [Just 10, Just 20], [Just 5] ]
[ [Just 10, Just 20], [Just 5] ] :: Num a => [[Maybe a]]
I'd like to apply this to sequence:
Prelude> :t sequence
sequence :: Monad m => [m a] -> m [a]
The Monad m in the above List is: [a], as I understand, so I'd expect the types to line up as:
sequence :: Monad m => [m a] -> m [a]
[[a]] -> [[a]]
Assuming that's right, then please help me understand the output:
Prelude> sequence [ [Just 10, Just 20], [Just 5] ]
[[Just 10,Just 5],[Just 20,Just 5]]
It might be easier to do this with just Ints instead of Maybe Ints:
> sequence [[10, 20], [5]]
[[10,5],[20,5]]
it :: [[Int]]
The type signature you deduced is correct, it does have type [[a]] -> [[a]] in this situation, where a ~ Int in my example or a ~ Maybe Int in your example. Whenever using sequence in the list monad, I like to think of it as an N-dimensional Cartesian product. It desugars to something like
sequence [a, b, c] = do
x <- a
y <- b
z <- c
return [x, y, z]
But with an arbitrary number of elements, not just 3. Some other examples might help explain:
sequence [["a1", "a2", "a3"], ["b1", "b2"], ["c1", "c2", "c3"]]
[
["a1","b1","c1"],["a1","b1","c2"],["a1","b1","c3"],["a1","b2","c1"],["a1","b2","c2"],["a1","b2","c3"],
["a2","b1","c1"],["a2","b1","c2"],["a2","b1","c3"],["a2","b2","c1"],["a2","b2","c2"],["a2","b2","c3"],
["a3","b1","c1"],["a3","b1","c2"],["a3","b1","c3"],["a3","b2","c1"],["a3","b2","c2"],["a3","b2","c3"]
]
If you study this output closely, you'll see that we have each element of the as matched with each element of the bs and each element from the cs. Since there are 3 as, 2 bs, and 3 cs, there are 3*2*3 == 18 elements in the output.
What sequence does is to turn something like
[foo, bar, baz]
into something like
do
x <- foo
y <- bar
z <- baz
return [x, y, z]
In your case, we have
do
x <- [Just 10, Just 5]
y <- [Just 5]
return [x, y]
which is the same as
foreach x in [Just 10, Just 5]
foreach y in [Just 5]
return [x, y]
in psuedo-OO syntax.
It should now be fairly obvious why you get the result you do.
A while ago I've asked a question about the function elem here, but I don't think the answer is fully satisfactory. My question is about the expression:
any (`elem` [1, 2]) [1, 2, 3]
We know elem is in a backtick so elem is an infix and my explanation is:
1 `elem` [1, 2] -- True
2 `elem` [1, 2] -- True
3 `elem` [1, 2] -- False
Finally it will return True since it's any rather than all. This looked good until I see a similar expression for isInfixOf:
any (isInfixOf [1, 2, 3]) [[1, 2, 3, 4], [1, 2]]
In this case a plausible explanation seems to be:
isInfixOf [1, 2, 3] [1, 2, 3, 4] -- True
isInfixOf [1, 2, 3] [1, 2] -- False
I wonder why they've been used in such different ways since
any (elem [1, 2]) [1, 2, 3]
will give an error and so will
any (`isInfixOf` [[1, 2, 3, 4], [1, 2]]) [1, 2, 3]
Your problem is with the (** a) syntactic sugar. The thing is that (elem b) is just the partial application of elem, that is:
(elem b) == (\xs -> elem b xs)
However when we use back ticks to make elem infix, we get a special syntax for infix operators which works like this:
(+ a) == (\ b -> b + a)
(a +) == (\ b -> a + b)
So therefore,
(`elem` xs) == (\a -> a `elem` xs) == (\ a -> elem a xs)
while
(elem xs) == (\a -> elem xs a)
So in the latter case your arguments are in the wrong order, and that is what is happening in your code.
Note that the (** a) syntactic sugar works for all infix operators except - since it is also a prefix operator. This exception from the rule is discussed here and here.
Using back-ticks around a function name turns it into an infix operator. So
x `fun` y
is the same as
fun x y
Haskell also has operator sections, f.e. (+ 1) means \x -> x + 1.
So
(`elem` xs)
is the same as
\x -> x `elem` xs
or
\x -> elem x xs
or
flip elem xs
It's called partial application.
isInfixOf [1, 2, 3] returns a function that expects one parameter.
any (elem [1, 2]) [1, 2, 3] is an error because you're looking for an element [1, 2], and the list only contains numbers, so haskell cannot match the types.
I was playing with Haskell and ghci when I found this which really bothers me:
foldl (++) [[3,4,5], [2,3,4], [2,1,1]] []
I expected to get this: [3,4,5,2,3,4,2,1,1]
However it gets:
[[3,4,5],[2,3,4],[2,1,1]]
As far as I understand foldl, it should be this:
(([] ++ [3, 4, 5]) ++ [2, 3, 4]) ++ [2, 1, 1]
If I type this in ghci it really is [3,4,5,2,3,4,2,1,1].
And the other strange thing is this:
Prelude> foldl1 (++) [[3,4,5], [2, 3, 4], [2, 1, 1]]
[3,4,5,2,3,4,2,1,1]
I expect foldl and foldl1 to behave in the same way. So what does foldl actually do?
The order of arguments is wrong. The right one is:
foldl (++) [] [[3,4,5], [2,3,4], [2,1,1]]
(That is, first the accumulator, then the list.)
You switched the arguments around. foldl takes the accumulator's starting value first, then the list to fold. So what happens in your case is that foldl folds over the empty list and thus returns the starting value, which is [[3,4,5], [2, 3, 4], [2, 1, 1]]. This will do what you want:
foldl (++) [] [[3,4,5], [2, 3, 4], [2, 1, 1]]
You got the argument order wrong
Prelude> :t foldl
foldl :: (a -> b -> a) -> a -> [b] -> a
Prelude> :t foldl1
foldl1 :: (a -> a -> a) -> [a] -> a
The initial value comes first. In your case, your initial value was [[3,4,5],[2,3,4],[2,1,1]] and you folded over the empty list, so you got back the initial value.