Got stuck again while trying to learn some Haskell. What I'm trying to do is implementing a combined head/tail method for lists with error handling. The signature must look like this:
head' :: MonadPlus m => [a] -> m (a,[a])
However I'm a bit lost at how error handling with MonadPlus works. I tried the following:
head' xs = if (length xs > 0) then Just(head xs, tail xs) else Nothing
but it complains: Expected type: m (a, [a]) Actual type: Maybe (a, [a]). Just for fun I also tried:
head' xs = if (length xs > 0) then Just(head xs, tail xs) else Nothing `mplus` Nothing
but not only does that look redundant, it also does not work either.
Any hints appreciated!
Try this:
head' :: MonadPlus m => [a] -> m (a,[a])
head' xs = if null xs then mzero then return (head xs, tail xs)
mzero is the "nothing" or (indeed) "zero" value, which you can use here to model the absence of a result. It has type m x for any type x and monad with zero m, so it fits here.
Instead, return wraps any value in any monad. In particular, you can insert our (a,[a]) pair inside m. (This does not even require the monad to be a MonadPlus)
Note how in the code above we did not mention any specific monad: the code is indeed generic, so that it can work with any MonadPlus.
Lastly, I used null instead of length ... > 0 since null only examines the first constructor in the list, while length ... > 0 has to traverse it all.
You can actually remove the check by switching to pattern matching:
head' :: MonadPlus m => [a] -> m (a,[a])
head' [] = mzero
head' (x:xs) = return (x, xs)
Related
I am using the following fold to get the final monotonically decreasing sequence of a list.
foldl (\acc x -> if x<=(last acc) then acc ++ [x] else [x]) [(-1)] a
So [9,5,3,6,2,1] would return [6,2,1]
However, with foldl I needed to supply a start for the fold namely [(-1)]. I was trying to turn into to a foldl1 to be able to handle any range of integers as well as any Ord a like so:
foldl1 (\acc x -> if x<=(last acc) then acc ++ [x] else [x]) a
But I get there error:
cannot construct infinite type: a ~ [a]
in the second argument of (<=) namely last acc
I was under the impression that foldl1 was basically :
foldl (function) [head a] a
But I guess this isn't so? How would you go about making this fold generic for any Ord type?
I was under the impression that foldl1 was basically :
foldl (function) [head a] a
No, foldl1 is basically:
foldl function (head a) (tail a)
So the initial element is not a list of head a, but head a.
How would you go about making this fold generic for any Ord type?
Well a quick fix is:
foldl (\acc x -> if x<=(last acc) then acc ++ [x] else [x]) [head a] (tail a)
But there are still two problems:
in case a is an empty list, this function will error (while you probably want to return the empty list); and
the code is not terribly efficient since both last and (++) run in O(n).
The first problem can easily be addressed by using pattern matching to prevent that scenario. But for the latter you better would for instance use a reverse approach. Like for instance:
f :: Ord t => [t] -> [t]
f [] = [] -- case when the empty list is given
f a = reverse $ foldl (\acc#(ac:_) x -> if x <= ac then (x:acc) else [x]) [head a] (tail a)
Furthermore personally I am not a huge fan of if-then-else in functional programming, you can for instance define a helper function like:
f :: Ord t => [t] -> [t]
f [] = [] -- case when the empty list is given
f a = reverse $ foldl g [head a] (tail a)
where g acc#(ac:_) x | x <= ac = (x:acc)
| otherwise = [x]
Now reverse runs in O(n) but this is done only once. Furthermore the (:) construction runs in O(1) so all the actions in g run in O(1) (well given the comparison of course works efficient, etc.) making the algorithm itself O(n).
For your sample input it gives:
*Main> f [9,5,3,6,2,1]
[6,2,1]
The type of foldl1 is:
Foldable t => (a -> a -> a) -> t a -> a
Your function argument,
\acc x -> if x<=(last acc) then acc ++ [x] else [x]
has type:
(Ord a) => [a] -> a -> [a]
When Haskell's typechecker tries typechecking your function, it'll try unifying the type a -> a -> a (the type of the first argument of foldl1) with the type [a] -> a -> [a] (the type of your function).
To unify these types would require unifying a with [a], which would lead to the infinite type a ~ [a] ~ [[a]] ~ [[[a]]]... and so on.
The reason this works while using foldl is that the type of foldl is:
Foldable t => (b -> a -> b) -> b -> t a -> b
So [a] gets unified with b and a gets unified with the other a, leading to no problem at all.
foldl1 is limited in that it can only take functions which deal with only one type, or, in other terms, the accumulator needs to be the same type as the input list (for instance, when folding a list of Ints, foldl1 can only return an Int, while foldl can use arbitrary accumulators. So you can't do this using foldl1).
With regards to making this generic for all Ord values, one possible solution is to make a new typeclass for values which state their own "least-bound" value, which would then be used by your function. You can't make this function as it is generic on all Ord values because not all Ord values have sequence least bounds you can use.
class LowerBounded a where
lowerBound :: a
instance LowerBounded Int where
lowerBound = -1
finalDecreasingSequence :: (Ord a, LowerBounded a) => [a] -> [a]
finalDecreasingSequence = foldl buildSequence lowerBound
where buildSequence acc x
| x <= (last acc) = acc ++ [x]
| otherwise = [x]
You might also want to read a bit about how Haskell does its type inference, as it helps a lot in figuring out errors like the one you got.
in Data.List, I saw this unfamiliar pattern match:
{-# NOINLINE [1] unsafeTake #-}
unsafeTake :: Int -> [a] -> [a]
unsafeTake !_ [] = []
unsafeTake 1 (x: _) = [x]
unsafeTake m (x:xs) = x : unsafeTake (m - 1) xs
My understanding is that ! removes thunks. Okay, but _ is ignored. There's something I'm not understanding. Clarification is appreciated.
That is a BangPattern. It is a annotation to tell the compiler, that this function should behave strict in its first argument. It is equivalent to the following code:
unsafeTake :: Int -> [a] -> [a]
unsafeTake x [] = x `seq` []
unsafeTake 1 (x: _) = [x]
unsafeTake m (x:xs) = m `seq` (x : unsafeTake (m - 1) xs)
And that the field is strict, means that if the first argument happens to be bottom, then the program halts:
unsafeTake (error "kaboom") []
This will throw kaboom with the strictness annotation, but it won't happen if it doesn't have it.
You can also place Bang Patterns into data type definitions:
data Tree a = Branch (Tree a) !a (Tree a)
| Empty
Then it will always evaluate the field containing a to its weak head normal form. This means that it won't evaluate the whole structure. From the haskell wiki
a constructor (eventually applied to arguments) like True, Just (square 42) or (:) 1
a built-in function applied to too few arguments (perhaps none) like (+) 2 or sqrt.
or a lambda abstraction \x -> expression.
It tells the compiler that even if the second argument is [], while it then knows it can apply the first alternative, it should still evaluate the first argument to head normal form. This means that unsafeTake is 'strict' in its first argument.
You can see the result if you try to evaluate unsafeTake (last (repeat 0)) [] compared to the same with take.
In Haskell, the default ordering for [a], given an ordering on a, seems to be a lexicographic ordering (side question: where can I find out if this is really the case)? What I want is a graded lexicographic ordering (also called "length plus lexicographic" ordering).
How would I specify that I want comparisons to be done in a graded lexicographical manner? I want it for only one type, not for all [a]. I tried this:
instance Ord [Int] where
compare xs ys = case compare (length xs) (length ys) of
LT -> LT
GT -> GT
EQ -> lexicographic_compare xs ys
but got this error message:
> [1 of 1] Compiling Main ( test.hs, interpreted )
test.hs:1:10:
Illegal instance declaration for `Ord [Int]'
(All instance types must be of the form (T a1 ... an)
where a1 ... an are *distinct type variables*,
and each type variable appears at most once in the instance head.
Use -XFlexibleInstances if you want to disable this.)
In the instance declaration for `Ord [Int]'
Failed, modules loaded: none.
Thanks for any and all help!
This is a typical application for a newtype wrapper:
newtype GradedLexOrd a = GradedLexOrd { runGradedLexOrd :: [a] }
instance (Ord a) => Ord (GradedLexOrd a) where
compare (GradedLexOrd xs) (GradedLexOrd ys) = gradedLexOrd xs ys
gradedLexOrd :: Ord a => [a] -> [a] -> Ordering
gradedLexOrd = comparing length <> compare -- Nice Monoid-based implementation,
--due to Aaron Roth (see answer below)
Alternatively, you could openly use lists, but instead of the Ord constrained functions like sort use the more general alternatives which accept a custom comparison function, e.g. sortBy gradedLexOrd.
There are two questions here:
How does Ord [a] looks like?
Of course you can experiment within GHCi, but maybe you want something more reliable. This is surprisingly difficult, especially as the definition of Lists is (due to their special syntax) built into the compiler. Let’s ask GHCi:
Prelude> :info []
data [] a = [] | a : [a] -- Defined in `GHC.Types'
instance Eq a => Eq [a] -- Defined in `GHC.Classes'
instance Monad [] -- Defined in `GHC.Base'
instance Functor [] -- Defined in `GHC.Base'
instance Ord a => Ord [a] -- Defined in `GHC.Classes'
instance Read a => Read [a] -- Defined in `GHC.Read'
instance Show a => Show [a] -- Defined in `GHC.Show'
It says that the instance is defined in GHC.Classes, which we find in GHC’s git repo, and there it says:
instance (Ord a) => Ord [a] where
{-# SPECIALISE instance Ord [Char] #-}
compare [] [] = EQ
compare [] (_:_) = LT
compare (_:_) [] = GT
compare (x:xs) (y:ys) = case compare x y of
EQ -> compare xs ys
other -> other
So yes, it is indeed the lexicographic ordering.
How to overwrite the ordering?
Don’t. There is an instance for [a] and there can be only one. With FlexibleInstances and OverlappingInstances, you could make it use an alternative instance for, say, [Int], but it is bad style. As leftaroundabout writes, use a NewtypeWrapper for it, or use parametrized functions like sortBy.
Creating a whole new Ord instance for lists of Ints seems a bit heavyweight to my taste (not to mention that you may be sowing confusion: someone who comes along to your code later will probably expect the default, non-graded lexicographic comparison behavior).
If you're merely hoping not to have to copy your custom comparison code every time you use sortBy or the like, there's actually a fairly lightweight way of defining chained comparison functions like yours on the spot. Ordering, as it happens, is an instance of Monoid, which means you can compare two things according to a succession of criteria, then combine the resulting Orderings of those comparisons using the Monoid function, mappend (recently abbreviated to <>). This is all explained in some detail in the Learn You a Haskell chapter on Monoids, etc., which is where I picked up the trick. So:
import Data.Monoid ((<>))
import Data.Ord (comparing)
gradedLexicographicCompare :: (Ord a) => [a] -> [a] -> Ordering
gradedLexicographicCompare xs ys = comparing length xs ys <> comparing id xs ys
(Of course, comparing id is just compare, but for the sake of uniformity...) Then it becomes relatively unburdensome to write things like
f = ... sortBy s ...
where
...
s xs ys = comparing length xs ys <> compare xs ys
...
And this also has the virtue that your successor will see immediately that you're using a custom comparison function.
Update: leftaroundabout points out below that we can achieve even greater elegance -- this is Haskell after all, and in Haskell we can always achieve greater elegance -- by making use of the monoid instance, instance Monoid b => Monoid (a -> b). That is, a function whose result is a monoid can itself be considered a monoid. The instance is given by
instance Monoid b => Monoid (a -> b) where
mempty _ = mempty
mappend f g x = f x `mappend` g x (1)
Now let's indulge in a little equational reasoning and see what comparing length <> compare expands to according to this instance. Applying (1) once, we have
comparing length <> compare
= mappend (comparing length) compare
= \xs -> mappend ((comparing length) xs) (compare xs) (2)
But ((comparing length) xs) :: [a] -> Ordering and (compare xs) :: (Ord a) => a -> Ordering are themselves functions whose results are monoids, namely Orderings, so we can apply (1) a second time to obtain
mappend ((comparing length) xs) (compare xs)
= \ys -> mappend (((comparing length) xs) ys) ((compare xs) ys) (3)
But now (((comparing length) xs) ys) and ((compare xs) ys) are fully applied functions. Specifically, they are Orderings, and from the original answer we know how to combine two Orderings using mappend from the Ordering instance of Monoid. (Note that we are not using mappend from (1).) Writing everything down in one big chain, we have
comparing length <> compare
= mappend (comparing length) compare [definition of <>]
= \xs -> mappend ((comparing length) xs) (compare xs) [by (1)]
= \xs -> (\ys -> mappend (((comparing length) xs) ys) ((compare xs) ys)) [substituting (3) in (2)]
= \xs -> \ys -> mappend (comparing length xs ys) (compare xs ys) [function application is left associative]
= \xs -> \ys -> comparing length xs ys <> compare xs ys [definition of <>]
And the last line of this expansion is just our original gradedLexicographicCompare! After a long, long digression, then, the punchline is that we can write the elegantly points-free
gradedLexicographicCompare = comparing length <> compare
Pretty.
I admit this is my homework. But I really couldn't find a good solution after working hard on it.
There might be some stupid ways to accomplish this, like:
myHead (x:[]) = x
myHead (x:y:xs) = fst (x, y)
But I don't think that's what the teacher wants.
BTW, error-handling is not required.
Thanks in advance!
There's a very natural function that's not in the prelude called "uncons" which is the inverse of uncurried cons.
cons :: a -> [a] -> [a]
uncurry cons :: (a, [a]) -> [a]
uncons :: [a] -> (a, [a])
uncons (x:xs) = (x, xs)
You can use it to implement head as
head = fst . uncons
Why is uncons natural?
You can think of a list as the datatype that's defined through the use of two constructor functions
nil :: [a]
nil = []
cons :: (a, [a]) -> [a]
cons (a,as) = a:as
You can also think of it as the data type which is deconstructed by a function
destruct :: [a] -> Maybe (a, [a])
destruct [] = Nothing
destruct (a:as) = Just (a, as)
It's well beyond this answer to explain why those are so definitively tied to the list type, but one way to look at it is to try to define
nil :: f a
cons :: (a, f a) -> f a
or
destruct :: f a -> Maybe (a, f a)
for any other container type f. You'll find that they all have very close relationships with lists.
You can almost already see uncons in the second case of the definition of destruct, but there's a Just in the way. This is uncons is better paired with head and tail which are not defined on empty lists
head [] = error "Prelude.head"
so we can adjust the previous answer to work for infinite streams. Here we can think of infinite streams as being constructed by one function
data Stream a = Next a (Stream a)
cons :: (a, Stream a) -> Stream a
cons (a, as) = Next a as
and destructed by one function
uncons :: Stream a -> (a, Stream a)
uncons (Next a as) = (a, as)
-- a. k. a.
uncons stream = (head stream, tail stream)
the two being inverses of one another.
Now we can get head for Streams by getting the first element of the return tuple from uncons
head = fst . uncons
And that's what head models in the Prelude, so we can pretend like lists are infinite streams and define head in that way
uncons :: [a] -> (a, [a])
uncons (a:as) = (a, as)
-- a. k. a.
uncons list = (head list, tail list)
head = fst . uncons
Perhaps you're expected write to your own cons List type, then it might make more sense. Although type synonyms can't be recursive, so you end up using a non-tuple data constructor, making the tuple superfluous.. it would look like:
data List a = Nil | List (a, List a)
deriving( Show )
head :: List a -> a
head (List c) = fst c
Like already said in the comments, this is just a silly task and you won't get something you could call a good implementation of head.
Your solution, for those requirements, is just fine – as the only change I would replace (x:y:xs) with (x:y:_) since xs isn't used at all (which would actually cause a compiler warning in some settings). In fact, you could do that with y as well:
myHead (x:_:_) = fst (x, undefined)
There would be alternatives that look perhaps not quite so useless use of fst, i.e. don't just build a tuple by hand and immediately deconstruct it again:
myHead' [x] = x
myHead' xs = myHead' . fst $ splitAt 1 xs
myHead'' = foldr1 $ curry fst
myHead''' = fromJust . find ((==0) . fst) . zip [0..]
but you could rightfully say that these are just ridiculous.
The following line
filterM (\x -> Just (x > 0)) [2, 1, 0, -1]
outputs
Just [2,1]
and the line
filterM (\x -> Just (x > 0)) []
shows
Just []
But I would like it to output Nothing. What can be done to possibly introduce some change that would work for all monad functions working with lists? So should I use something else instead of filterM or I can do some inheritance from Maybe monad?
You could use mfilter to convert your Just [] to nothing based on a predicate:
mfilter (not . null) . filterM (Just . (>0)) $ []
Define:
flatten :: Maybe [a] -> Maybe [a]
flatten Nothing = Nothing
flatten (Just []) = Nothing
flatten x = x
Then
flatten $ filterM (\x -> Just (x > 0)) []
I'm not sure what you mean in terms of working for all monad functions working with lists. There is no way to modify the list monad so that this will happen automatically with any monad function, as this would require effectively changing the bind of some other unknown monad. Likewise, changing all of the monad functions would be a bit time consuming.
My suggestion is to use composability. What we want is to fail in the outer monad m if the inner monad, list, is failing. This should be fairly easy, although I'm not sure what to call it, so I will use failing.
failing :: MonadPlus m => m [a] -> m [a]
failing = (=<<) $ \l -> case l of
[] -> mzero
_ -> return l
Then failing $ filterM (\x -> Just (x > 0)) [] should do what you want.
I'm not sure why you're involving Maybe at all in this case though (as your filter conditions both only use Just), but I'm assuming you have some other reason for doing this, or some other condition that sometimes fails.