Converting Function To Maybe Type - haskell

I am trying to convert a function of maximum utilizing a foldr function to one that also incorporates the maybe type. It is originally:
maximum' :: (Ord a) => [a] -> a
maximum' = foldr1 (\x acc -> if x > acc then x else acc)
It works perfectly with sets, but not with the empty set. I want to convert it to use maybe types instead.
My thought process was:
mymax :: (Ord a) => [Maybe a] -> Maybe a
mymax = foldr (\(Just x) (Just b) -> if ((Just x) > (Just b)) then (Just x) else (Just b)) Nothing
It compiles with no errors and works when I give it the empty set. However, when I give it a set with numbers in it, it no longer works! Can someone point me in the right direction on how I can get the functionality of it also getting the maximum from a list of maybes?
I really want to use the foldr function in my solution....
I've now tried:
mymax :: (Ord a) => [a] -> Maybe a
mymax = foldr (\x b -> if x > b then (Just x) else (Just b)) Nothing
But it will not compile:
Couldn't match expected type `Maybe b -> Maybe a'
with actual type `Maybe a0'
In the return type of a call of `Just'
Probable cause: `Just' is applied to too many arguments
In the expression: (Just x)
In the expression: if x > b then (Just x) else (Just b)
Failed, modules loaded: none.

If you want to do it in a single foldr, we can exploit the fact that Ord a => Ord (Maybe a), that is, any ordering on a can be extended to an ordering on Maybe a.
We also have Just x > Nothing, for all x :: Ord a => a.
mymax :: (Ord a) => [a] -> Maybe a
mymax = foldr (\x b -> let x' = Just x in if x' > b then x' else b) Nothing
-- equivalently
mymax = foldr (\x b -> let x' = Just x in max x' b) Nothing
mymax = foldr (\x' b -> max x' b) Nothing . map (\x -> Just x)
mymax = foldr max Nothing . map Just
If we want to do minimum, we'll have to do it a bit differently, since Nothing is the lower bound for the type Ord a => Maybe a, which means that foldr min Nothing . map Just == const Nothing, which isn't useful.
mymin :: (Ord a) => [a] -> Maybe a
mymin = foldr (\x b -> case b of
Nothing -> Just x
Just y -> Just (min x y)
) Nothing
-- which is equivalent to
mymin = foldr (\x b -> Just $ case b of
Nothing -> x
Just y -> min x y
) Nothing
mymin = foldr (\x b -> Just $ maybe x (min x) b) Nothing
mymin = foldr (\x -> Just . maybe x (min x)) Nothing
Honestly, though, I think pattern matching makes solutions a lot clearer
mymax [] = Nothing
mymax (a:as) = Just $ foldr max a as
mymin [] = Nothing
mymin (a:as) = Just $ foldr min a as

I think you actually want mymax to have type (Ord a) => [a] -> Maybe a. Here's a potential implementation that uses pattern matching and your original maximum' function:
mymax :: (Ord a) => [a] -> Maybe a
mymax [] = Nothing
mymax xs = Just (maximum' xs)
Also, Learn You A Haskell is a great resource if you haven't already come across it!

Related

How can I map a function to a list and stop when a condition is fulfilled and tell me if it stopped or reached the end?

I want to apply a function over a list, but if, at any moment, a result returned by the function is of a certain kind, then I don't want to continue to iterate over the rest of the elements.
I know I could achieve this with this function:
example p f ls = takeWhile p $ map f ls
The thing is that I would like to know if it reached the end of the list, or if it failed to do so.
I thought of this function, but it seems a bit cumbersome:
haltmap :: Eq a => (a -> Bool) -> (b -> a) -> [a] -> [b] -> Either [a] [a]
haltmap _ _ acc [] = Right acc
haltmap p f acc (h:t)
| p output = Left acc
| otherwise = haltmap p f (acc ++ [output]) t
where output = f h
I use Left and Right to know if it went through the entire list or not.
I'm sure there's a better way to do that.
I'd use span for this. It's like takeWhile but it gives you a pair with the remainder of the list as well as the matching part, like this:
> span (<3) [1,2,3,2,1]
([1,2],[3,2,1])
Then you can check if the remainder is empty:
haltmap :: (a -> Bool) -> (b -> a) -> [b] -> Either [a] [a]
haltmap p f xs = (if null rest then Right else Left) ys
where
(ys, rest) = span p (map f xs)
You can use foldr for this. Because go does not evaluate the second argument unless needed, this will also work for infinite lists. (Will Ness also had an answer that also used foldr, but it seems they've deleted it).
import Data.Bifunctor (bimap)
haltmap :: Eq a => (b -> Bool) -> (a -> b) -> [a] -> Either [b] [b]
haltmap p f xs = foldr go (Right []) xs
where
go x a
| p output = let o = (output:) in bimap o o a
| otherwise = Left []
where output = f x
main = do
print $ haltmap (<5) (+1) [1..]
print $ haltmap (<12) (+1) [1..10]
Try it online!
Using a tuple with a Bool may be easier, though.
import Data.Bifunctor (second)
haltmap :: Eq a => (b -> Bool) -> (a -> b) -> [a] -> (Bool, [b])
haltmap p f xs = foldr go (True, []) xs
where
go x a
| p output = second (output:) a
| otherwise = (False, [])
where output = f x
haltmap (<5) (+1) [1..] //(False,[2,3,4])
haltmap (<12) (+1) [1..10] //(True,[2,3,4,5,6,7,8,9,10,11])
Try it online!
I found a solution with foldr, which is the following:
haltMap :: (a -> Bool) -> (b -> a) -> [b] -> Either [a] [a]
haltMap p f = foldr (\x acc -> if p x then Left []
else (either (\a -> Left (x:a)) (\b -> Right (x:b)) acc))
(Right []) . map f
Also, to return, instead of the partial list, the element which failed, all is needed it to change Left [] to Left x in the if clause, and change the (\a -> Left (x:a)) to Left in the else clause.

How to find Maximum element in List with maybe output

This code works
max_elem :: (Ord a) => [a] -> a
max_elem [x] = x
max_elem [] = error "No elements"
max_elem (x:xs)
|x > max_elem xs = x
|otherwise = max_elem xs
I want to have it so it returns Nothing if their are no elements and Just x for the maximum element
I tried the following
max_elem :: (Ord a) => [a] -> Maybe a
max_elem [x] = Just x
max_elem [] = Nothing
max_elem (x:xs)
|x > max_elem xs = Just x
|otherwise = max_elem xs
I got the following error. Recommendations to fix this please.
• Couldn't match expected type ‘a’ with actual type ‘Maybe a’
‘a’ is a rigid type variable bound by
the type signature for:
max_elem :: forall a. Ord a => [a] -> Maybe a
at <interactive>:208:13
• In the second argument of ‘(>)’, namely ‘max_elem xs’
In the expression: x > max_elem xs
In a stmt of a pattern guard for
an equation for ‘max_elem’:
x > max_elem xs
• Relevant bindings include
xs :: [a] (bound at <interactive>:211:13)
x :: a (bound at <interactive>:211:11)
max_elem :: [a] -> Maybe a (bound at <interactive>:209:1)
You get your error because of this line: x > max_elem xs. max_elem xs has type Maybe a where a is an element of a list. It has type a. You can't compare values of different types. a and Maybe a are different types. See Haskell equality table:
https://htmlpreview.github.io/?https://github.com/quchen/articles/blob/master/haskell-equality-table.html
Replace == operator with > and you will get the same table.
You can solve problem in your code by replacing x > max_elem xs with Just x > max_elem xs. Does it make sense to you?
As you can see, Maybe a data type has Ord a => Ord (Maybe a) instance which is actually really handy! So you can implement your function in even more concise way to utilize this Ord instance:
max_elem :: Ord a => [a] -> Maybe a
max_elem = foldr max Nothing . map Just
Though, this probably won't be the most efficient solution if you care about performance.
The error message was clear enough to solve your problem.
|x > max_elem xs = Just x
The problem is that you compare x which is a with max_elem which is Maybe a. That's why you got such error message. You can solve the problem with this code below.
max_elem :: (Ord a) => [a] -> Maybe a
max_elem [] = Nothing
max_elem (x:xs) = case (max_elem xs) of
Nothing -> Just x
Just y -> if x > y then Just x else Just y
We can generalize this task and work with all Foldables. Here we thus use the foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b function that folds a certain Foldable structure. We can do this with the function max . Just, and as initial element Nothing:
max_elem :: (Ord a, Foldable f) => f a -> Maybe a
max_elem = foldr (max . Just) Nothing
Note that this works since Haskell defines Maybe a to be an instance of Ord, given a is an instance of Ord, and it implements it in a way that Nothing is smaller than any Just element.
This makes the above definition perhaps a bit "unsafe" (in the sense that we here rely on the fact that from the moment we have a Just x, the max will select such Just x over a Nothing). When we would use min, this would not work (not without using some tricks).
We can also use pattern guards and thus solve the case where the list is empty in a different way, like:
max_elem :: Ord a => [a] -> Maybe a
max_elem [] = Nothing
max_elem l = Just (maximum l)
The problem is x > max_elem xs; max_elem xs is Maybe a, not a, meaning that it might return Nothing. However, you do know that it will only return Nothing if xs is empty, but you know xs won't be empty because you matched the case where it would using [x]. You can take advantage of this fact by writing a "non-empty" maximum:
max_elem_ne :: Ord a => a -> [a] -> a
max_elem_ne m [] = m
max_elem_ne m (x:xs)
| m > x = max_elem m xs
| otherwise = max_elem x xs
Or, alternatively, using max:
max_elem_ne :: Ord a => a -> [a] -> a
max_elem_ne m [] = m
max_elem_ne m (x:xs) = max_elem (max m x) xs
You can think of the first argument as the maximum value seen "so far", and the second list argument as the list of other candidates.
In this last form, you might have noticed that max_elem_ne is actually a just left fold, so you could even just write:
max_elem_ne :: Ord a => a -> [a] -> a
max_elem_ne = foldl' max
Now, with max_elem_ne, you can write your original max_elem:
Then you can write:
max_elem :: Ord a => [a] -> Maybe a
max_elem [] = Nothing
max_elem (x:xs) = Just (max_elem_ne x xs)
So you don't have to do any extraneous checks (like you would if you redundantly pattern matched on results), and the whole thing is type-safe.
You can also use the uncons :: [a] -> Maybe (a,[a]) utility function with fmap and uncurry to write:
max_elem :: Ord a => [a] -> Maybe a
max_elem = fmap (uncurry max_elem_ne) . uncons

Haskell - MinMax using foldr

I am looking for a Haskell function that takes a list as an argument and returns a tuple (min, max), where min is the minimal value of the list and max is the maximal value.
I already have this:
maxMinFold :: Ord a => [a] -> (a, a)
maxMinFold list = foldr (\x (tailMin, tailMax) -> (min x tailMin) (max x tailMax)) -- missing part
Could you help me what to add to the missing part? (or tell me what I am doing wrong)
Thanks a lot
You take the head and use that as the fist min and max and then fold over the tail.
maxMinFold :: Ord a => [a] -> (a, a)
maxMinFold (x:xs) = foldr (\x (tailMin, tailMax) -> (min x tailMin, max x tailMax)) (x,x) xs
As regards your answer, your fold function is not returning the right type.
Note that
foldr :: (a -> b **-> b**) -> b -> [a] -> b
In particular you need to be returning a b, which is a tuple in your case
Since you always have to traverse the whole list to find the minimum and the maximum here is the solution with foldl:
maxMinList :: Ord a => [a] -> (a,a)
maxMinList (x:xs) = foldl (\(l,h) y -> (min l y, max h y)) (x,x) xs
To do this efficiently with foldr,
data NEList a = NEList a [a]
-- deriving (Eq, Ord, Show, Read, Functor, Foldable, Traversable)
minMax :: Ord a => NEList -> (a, a)
minMax (NEList x0 xs) = foldr go (,) xs x0 x0 where
go x r mn mx
| x < mn = r x mx
| mx < x = r mn x
| otherwise = r mn mx
Another, similar, approach:
minMaxM :: Ord a => [a] -> Maybe (a, a)
minMaxM xs = foldr go id xs Nothing where
go x r Nothing = r (Just (x, x))
go x r mnmx#(Just (mn, mx))
| x < mn = r (Just (x, mx))
| mx < x = r (Just (mn, x))
| otherwise = r mnmx
It would be nice if the minMax function returned Nothing in the case of an empty list. Here is a version which does that.
import Control.Arrow
import Data.Maybe
import Data.Foldable
minMax :: (Ord a) => [a] -> Maybe (a,a)
minMax = foldl' (flip $ \ x -> Just . maybe (x,x) (min x *** max x)) Nothing
This uses foldl' instead of foldr.

No instance for (Num a) arising from a use of `sum' - Instance Num

this function works fine:
fromDigits :: [Int] -> Int
fromDigits n = sum (zipWith (\x y -> x*y) (n) (f n 0))
where
f :: [Int] -> Int -> [Int]
f n x = if (x==length n) then []
else (10^x):f n (x+1)
But if i want to change the type signature from the function, it does not work:
fromDigits :: (Num a) => [a] -> a
fromDigits n = sum (zipWith (\x y -> x*y) (n) (f n 0))
where
f :: (Num a) => [a] -> a -> [a]
f n x = if (x==length n) then []
else (10^x):f n (x+1)
Shouldn't this work too?
Almost, but not quite. The basic problem is that length has type [a]->Int. This will work:
fromDigits :: Num a => [a] -> a
fromDigits n = sum (zipWith (\x y -> x*y) (n) (f n 0))
where
f :: Num b => [b] -> Int -> [b]
f n x = if (x==length n) then []
else (10^x):f n (x+1)
As Oleg Grenrus points out, one should always be careful to check if Int might overflow. It is in fact possible for this to happen if Int is 30, 31, or 32 bits, although it is relatively unlikely. However, if that is a concern, there is a way around it, using another function:
lengthIsExactly :: Integral n => n -> [a] -> Bool
lengthIsExactly = -- I'll let you figure this one out.
-- Remember: you can't use `length` here,
-- and `genericLength` is horribly inefficient,
-- and there's a completely different way.
You can make it easier to see how the types of fromDigits and f match up using a GHC extension. Enable the extension by adding
{-# LANGUAGE ScopedTypeVariables #-}
to the very top of your source file. Then you can write
fromDigits :: forall a . Num a => [a] -> a
fromDigits n = sum (zipWith (\x y -> x*y) (n) (f n 0))
where
f :: [a] -> Int -> [a]
f n x = if (x==length n) then []
else (10^x):f n (x+1)
This way, it's clear that the list arguments all have the same type.
The problem is that you are using other functions that require even more of type a than just Num a
(^) requires "Integral a"
This works
fromDigits' :: (Num a, Integral a)=>[a] -> a
fromDigits' n = sum (zipWith (\x y -> x*y) (n) (f n 0))
where
f :: (Num a, Integral a)=>[a] -> a -> [a]
f n x = if (x==fromIntegral (length n)) then []
else (10^x):f n (x+1)

How does the expression `ap zip tail` work

I wondered how to write f x = zip x (tail x) in point free. So I used the pointfree program and the result was f = ap zip tail. ap being a function from Control.Monad
I do not understand how the point free definition works. I hope I can figure it out if I can comprehend it from the perspective of types.
import Control.Monad (ap)
let f = ap zip tail
let g = ap zip
:info ap zip tail f g
ap :: Monad m => m (a -> b) -> m a -> m b
-- Defined in `Control.Monad'
zip :: [a] -> [b] -> [(a, b)] -- Defined in `GHC.List'
tail :: [a] -> [a] -- Defined in `GHC.List'
f :: [b] -> [(b, b)] -- Defined at <interactive>:3:5
g :: ([a] -> [b]) -> [a] -> [(a, b)]
-- Defined at <interactive>:4:5
By looking at the expression ap zip tail I would think that zip is the first parameter of ap and tail is the second parameter of ap.
Monad m => m (a -> b) -> m a -> m b
\--------/ \---/
zip tail
But this is not possible, because the types of zip and tail are completely different than what the function ap requires. Even with taking into consideration that the list is a monad of sorts.
So the type signature of ap is Monad m => m (a -> b) -> m a -> m b. You've given it zip and tail as arguments, so let's look at their type signatures.
Starting with tail :: [a] -> [a] ~ (->) [a] [a] (here ~ is the equality operator for types), if we compare this type against the type of the second argument for ap,
(->) [x] [x] ~ m a
((->) [x]) [x] ~ m a
we get a ~ [x] and m ~ ((->) [x]) ~ ((->) a). Already we can see that the monad we're in is (->) [x], not []. If we substitute what we can into the type signature of ap we get:
(((->) [x]) ([x] -> b)) -> (((->) [x]) [x]) -> (((->) [x]) b)
Since this is not very readable, it can more normally be written as
([x] -> ([x] -> b)) -> ([x] -> [x]) -> ([x] -> b)
~ ([x] -> [x] -> b ) -> ([x] -> [x]) -> ([x] -> b)
The type of zip is [x] -> [y] -> [(x, y)]. We can already see that this lines up with the first argument to ap where
[x] ~ [x]
[y] ~ [x]
[(x, y)] ~ b
Here I've listed the types vertically so that you can easily see which types line up. So obviously x ~ x, y ~ x, and [(x, y)] ~ [(x, x)] ~ b, so we can finish substituting b ~ [(x, x)] into ap's type signature and get
([x] -> [x] -> [(x, x)]) -> ([x] -> [x]) -> ([x] -> [(x, x)])
-- zip tail ( ap zip tail )
-- ap zip tail u = zip u (tail u)
I hope that clears things up for you.
EDIT: As danvari pointed out in the comments, the monad (->) a is sometimes called the reader monad.
There are two aspects to understanding this:
The type magic
The information flow of the implementation
Firstly, this helped me understand the type magic:
1) zip : [a] → ( [a] → [(a,a)] )
2) tail : [a] → [a]
3) zip <*> tail : [a] → [(a,a)]
4) <*> : Applicative f ⇒ f (p → q) → f p → f q
In this case, for <*>,
5) f x = y → x
Note that in 5, f is a type constructor. Applying f to x produces a type. Also, here = is overloaded to mean equivalence of types.
y is currently a place-holder, in this case, it is [a], which means
6) f x = [a] -> x
Using 6, we can rewrite 1,2 and 3 as follows:
7) zip : f ([a] → [(a,a)])
8) tail : f [a]
9) zip <*> tail : f ([a] → [(a,a)]) → f [a] → f [(a,a)]
So, looking at 4, we are substituting as follows:
10) p = [a]
11) q = [(a,a)]
12) f x = [a] → x
(Repetition of 6 here again as 12 )
Secondly, the information flow, i.e. the actual functionality. This is easier, it is clear from the definition of <*> for the Applicative instance of y →, which is rewritten here with different identifier names and using infix style:
13) g <*> h $ xs = g xs (h xs)
Substituting as follows:
14) g = zip
15) h = tail
Gives:
zip <*> tail $ xs (Using 14 and 15)
==
zip xs (tail xs) (Using 13 )

Resources