How to find Maximum element in List with maybe output - haskell

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

Related

Creating a safe version of Haskell 'init' function

I'm working my way through "Real World Haskell," and the assignment is to make safe versions of head, tail, last, and init. I've succeeded on the first three, but the Maybe typeclass is killing me on init.
Here is my code:
-- safeInit
safeInit :: [a] -> Maybe [a]
safeInit [] = Nothing
safeInit (x:xs) = if null xs
then Just [x]
else x : (safeInit xs)
And here are the resultant errors on loading into GHCI (the function starts on line 23 of the original file:
[1 of 1] Compiling Main ( ch04.exercises.hs, interpreted )
> ch04.exercises.hs:27:26: error:
> • Couldn't match expected type ‘Maybe [a]’ with actual type ‘[a]’
> • In the expression: x : (safeInit xs)
> In the expression: if null xs then Just [x] else x : (safeInit xs)
> In an equation for ‘safeInit’:
> safeInit (x : xs) = if null xs then Just [x] else x : (safeInit xs)
> • Relevant bindings include
> xs :: [a] (bound at ch04.exercises.hs:25:13)
> x :: a (bound at ch04.exercises.hs:25:11)
> safeInit :: [a] -> Maybe [a] (bound at ch04.exercises.hs:24:1) | 27 | else x : (safeInit xs) |
> ^^^^^^^^^^^^^^^^^
>
> ch04.exercises.hs:27:31: error:
> • Couldn't match expected type ‘[a]’ with actual type ‘Maybe [a]’
> • In the second argument of ‘(:)’, namely ‘(safeInit xs)’
> In the expression: x : (safeInit xs)
> In the expression: if null xs then Just [x] else x : (safeInit xs)
> • Relevant bindings include
> xs :: [a] (bound at ch04.exercises.hs:25:13)
> x :: a (bound at ch04.exercises.hs:25:11)
> safeInit :: [a] -> Maybe [a] (bound at ch04.exercises.hs:24:1) | 27 | else x : (safeInit xs) |
> ^^^^^^^^^^^ Failed, no modules loaded.
Any way I mark or don't mark either the x or xs on the last two lines with Just, I get different, but very much related, typing errors. What subtlety on using the Maybe type with lists am I missing?
The main reason why this does not work is because your expression x : safeInit xs will not typecheck. Indeed, safeInit xs is a Maybe [a], but (:) has type (:) :: a -> [a] -> [a], so the types do not match.
There is also a semantical error. If null xs is True, then you should return Just [] instead of Just [x], since then x is the last element in the list.
You can make use of fmap :: Functor f => (a -> b) -> f a -> f b (so for f ~ Maybe, fmap is fmap :: (a -> b) -> Maybe a -> Maybe b), to alter a value that is wrapped in a Just:
safeInit :: [a] -> Maybe [a]
safeInit [] = Nothing
safeInit [_] = Just []
safeInit (x:xs) = fmap (x:) (safeInit xs)
but this will result in a lot of wrapping and unwrapping of values in a Just. It also means that for an infinite list, it will get stuck in an infinite loop. We can simply check if the list contains at least on element, and then perform the init logic as the result of a function we wrap in a Just:
safeInit :: [a] -> Maybe [a]
safeInit [] = Nothing
safeInit (x:xs) = Just (go xs x)
where go [] _ = []
go (x2:xs) x = x : go xs x2
One interesting problem is how to write safeInit in terms of foldr. Aside from the fun of the puzzle, this allows it to participate in the list fusion optimization in GHC as a "good consumer", which can improve performance in some cases. We start with the first (naive) version in Willem Van Onsem's answer:
safeInit0 :: [a] -> Maybe [a]
safeInit0 [] = Nothing
safeInit0 [_] = Just []
safeInit0 (x:xs) = fmap (x:) (safeInit0 xs)
The first problem with this is that it's not shaped quite like a fold: it has separate cases for [p] and for p:q:rs. A classic trick for patching this up is to pass a Maybe carrying the previous value in the list.
safeInit1 :: [a] -> Maybe [a]
safeInit1 xs0 = go xs0 Nothing
where
-- This first case only happens when
-- the whole list is empty.
go [] Nothing = Nothing
go [] (Just x) = Just [x]
go (x:xs) Nothing = go xs (Just x)
go (x:xs) (Just prev) = (prev:) <$> go xs (Just x)
The next problem is semantic: it doesn't work right with infinite or partially defined arguments. We want
safeInit [1..] = Just [1..]
but safeInit1 will diverge in this case, because fmap is necessarily strict in its Maybe argument. But it turns out there's a bit of information we can use: fmap will only be applied to a Just value in this case. Exercise: prove that.
We'll take advantage of that by representing Maybe [a] in a weird way as (Bool, [a]), where Nothing is represented as (False, []) and Just xs is represented as (True, xs). Now we can be lazier:
safeInit2 :: [a] -> Maybe [a]
safeInit2 xs = case helper2 xs of
(False, _) -> Nothing
(True, xs) -> Just xs
helper2 :: [a] -> (Bool, [a])
helper2 xs0 = go xs0 Nothing
where
go [] Nothing = (False, [])
go [] _ = (True, [])
go (x:xs) mb = case mb of
Nothing -> (True, rest)
Just p -> (True, p:rest)
where
rest = snd (go xs (Just x))
Now this has precisely the shape of a fold:
safeInit3 :: [a] -> Maybe [a]
safeInit3 xs = case helper3 xs of
(False, _) -> Nothing
(True, xs) -> Just xs
helper3 :: [a] -> (Bool, [a])
helper3 xs0 = foldr go stop x0 Nothing
where
stop Nothing = (False, [])
stop _ = (True, [])
go x r mb = case mb of
Nothing -> (True, rest)
Just p -> (True, p:rest)
where
rest = snd (r (Just x))
You might worry that all these intermediate Maybes and pairs will cause performance problems, but in fact GHC is able to optimize them all away, producing something very much like Willem Van Onsem's optimized implementation.

Replace elements in the list

I need to implement a function that replaces elements in a list -- the
index to replace at is the fst in the tuple, and the snd in the tuple
is what to replace it with. and I am asked to use foldr or map function.
for example:
setElements [(1, 'a'), (-4, 't'), (3, 'b')] "#####" = "#a#b#"
the setElements function doesn't compile:
my code:
setElement :: Int -> a -> [a] -> [a]
setElement n x xs = if ((n < length xs) && n >= 0)
then (take n xs) ++ [x] ++ (drop (n + 1) xs)
else xs
setElements :: [(Int, a)] -> [a] -> [a]
setElements = foldr (\t l-> setElement (fst t) (snd t) l) []
I get:
• Couldn't match type ‘[a]’ with ‘[a] -> [a]’
Expected type: [(Int, a)] -> [a] -> [a]
Actual type: [(Int, a)] -> [a]
• Possible cause: ‘foldr’ is applied to too many arguments
In the expression: foldr (\ t l -> setElement (fst t) (snd t) l) []
In an equation for ‘setElements’:
setElements = foldr (\ t l -> setElement (fst t) (snd t) l) []
• Relevant bindings include
setElements :: [(Int, a)] -> [a] -> [a]
(bound at hw3.hs:79:1)
|
79 | setElements = foldr (\t l-> setElement (fst t) (snd t) l) []
|
How can I fix the error?
Let's look at your function:
setElements :: [(Int, a)] -> [a] -> [a]
setElements = foldr (\t l-> setElement (fst t) (snd t) l) []
and recall the type of foldr:
foldr :: (a -> b -> b) -> b -> [a] -> b
In your use of foldr, you have a as (Int, a) and b as [a]. And you only give it the first 2 arguments. So foldr (\t l-> setElement (fst t) (snd t) l) [] has type [(Int, a)] -> [a] - whereas setElements is supposed to have type [(Int, a)] -> [a] -> [a]. Note how these match exactly with the "actual type" and "expected type" reported by GHC in the error message.
To fix this, I would actually take a step backwards. Folding is the right idea - your setElement function already modifies the original list (its third argument) based on an index and new value, and what you want is to take a list of pairs encoding this data, and keep on applying this function to update the original list repeatedly. (Of course this is Haskell so data is immutable - you're not literally updating it in place, but simply returning a new list each time. But sometimes talking loosely like this is easier.)
That's exactly what a fold is. Let's try to write it out, without trying to be too fancy with a "point-free" approach, but instead fully applying it:
setElements :: [(Int, a)] -> [a] -> [a]
setElements ps as = foldr myFunction as ps
where myFunction = undefined
The undefined here is just a placeholder - it will cause a runtime error if you try to use the function (but won't cause a compilation error), and I've put it there because we need to think about that, the fold function usually being the trickiest part of implementing a fold. But let's check we understand what the other terms are doing: the list we are actually "walking along" is the list of (Int, a) terms that tell us what to insert and where - that's what I've called ps (the p is for "pair"). And because we are starting with the list of as - which I've logically called as here - then that should be the starting accumulator value, which is the second argument to foldr.
So all that remains is the fold function - which takes a pair and a list, and updates the list according to the values in the pair. Well this is the function you're already using:
\t l-> setElement (fst t) (snd t) l
or, rewritten with pattern matching (which I find much more readable, and for this reason I think is preferred by most Haskell developers):
\(i, a) as -> setElement i a as
So, substituting this in, we arrive at the following definition:
setElements :: [(Int, a)] -> [a] -> [a]
setElements ps as = foldr myFunction as ps
where myFunction = \(i, a) as -> setElement i a as
This now will compile and work correctly. But it's always worth taking a step back when you have a working function, and seeing if you can simplify its definition. In fact myFunction can be simplified quite a bit:
\(i, a) as -> setElement i a as
can first be "eta-reduced" to
\(i, a) -> setElement i a
which, using a standard library function, is simply uncurry setElement.
At this stage we clearly don't need a where clause any more (in fact we never did before, but imo it aids readability for any lambda which isn't fairly trivial), and can just write:
setElements :: [(Int, a)] -> [a] -> [a]
setElements ps as = foldr (uncurry setElement) as ps
In fact, while I wouldn't necessarily recommend it, if we're playing code golf you can even go a step further and just write:
setElements = flip . foldr . uncurry $ setElement
I personally think the ability to be able to express relatively complex functions in a concise way, as above, is definitely part of the allure of Haskell. But, rather than try to write something like this straight away, in my opinion it's always best to start with something very concrete showing how you want to transform your data - and, only after getting that working, look for a more concise representation if you want to.

Reflexive Closure

I have been working on a question about reflexive closure:
The reflexive closure of a relation R is the smallest relation bigger than R which is reflexive. In other words, it is R with whatever pairs added to make R reflexive. Write a function (reflClosure) which takes a list of pairs (standing for R) and returns a list of pairs which is the reflexive closure of R. You do not need to worry about the order in which pairs appear in your return value.
I came up with this solution but it seems quite sloppy and lack neatness.
-- QUESTION 2: Functions and relations
reflClosure :: (Eq a) => [(a,a)] -> [(a,a)]
reflClosure (x:xs) = nub ( (x:xs) ++ [ (x,x) | x <- (heads (x:xs)) ++ (tails
(x:xs)) ])
nub :: Eq a => [a] -> [a]
nub = nubBy (==)
nubBy :: (a -> a -> Bool) -> [a] -> [a]
nubBy eq [] = []
nubBy eq (x:xs) = x : nubBy eq (filter (\y -> not (eq x y)) xs)
heads :: (Eq a) => [(a,a)] -> [a]
heads list = nub [x | (x, _) <- list]
tails :: (Eq a) => [(a,a)] -> [a]
tails list = nub [x | (_,x) <- list]
exists :: (Eq a) => (a,a) -> [(a,a)] -> Bool
exists x xs = length (filter (==x) xs) > 0
-- TEST SET FOR Q2
{-
Your functions should have the following behaviour:
reflClosure [(1,2),(3,2)] = [(1,2),(3,2),(1,1),(2,2),(3,3)]
reflClosure [(1,1),(3,5)] = [(1,1),(3,5),(3,3),(5,5)]
DO NOT WORRY ABOUT THE ORDER IN WHICH PAIRS APPEAR IN YOUR LIST
-}
Is there an easier way to do this? Explanation would be incredibly useful to learn from as well.
A nicer way to write heads and tails is the following:
heads :: (Eq a) => [(a,a)] -> [a]
heads = nub . map fst
tails :: (Eq a) => [(a,a)] -> [a]
tails = nub . map snd
It's point-free, plus it uses the more "functional" map rather than a list comprehension.
However, the fact that you need both means there's an even nicer way:
(heads (x:xs), tails (x:xs)) = (\(a,b) -> (nub a) (nub b)) $ unzip (x:xs)
Getting the fsts and the snds is equivalent to an unzip.
Also, you can simplify the signature of exists:
exists :: (Eq a) => a -> [a] -> Bool
exists x xs = length (filter (==x) xs) > 0
since nothing depends on the input being a list of pairs.
Data.List already defines nubBy, so I'm not sure why you've defined it there.
It's not clear why you've defined reflClosure to match on (x:xs), because all you care about (apparently) is that the list is non-empty. Perhaps something like this:
reflClosure :: (Eq a) => [(a,a)] -> [(a,a)]
reflClosure [] = []
reflClosure xs =
let (as,bs) = unzip xs
in nub $ xs ++ [ (x,x) | x <- (nub as) ++ (nub bs) ]
Relations are isomorphic to sets of pairs, not lists of pairs, so it makes sense to model them as such. Note that all the Ord constraints below are there because the implementation of Set needs it.
Use the standard library sets because they are fast.
import Data.Set (Set)
import qualified Data.Set as Set
A type synonym to make the code easier to read:
-- A relation with underlying set s
type Relation s = Set (s,s)
Now we can write a function that gets all the members of the underlying set:
underlyingMembers :: Ord a => Relation a -> Set a
underlyingMembers r = (Set.map fst r) `Set.union` (Set.map snd r)
Once we have that, finding the reflexive closure of a relation is easy:
reflexiveClosure :: Ord a => Relation a -> Relation a
reflexiveClosure r = r `Set.union` (Set.map (\x -> (x,x)) (underlyingMembers r)
If you really need to work with lists, (you really shouldn't, though) you can fromList/toList:
listVersion :: Ord a => [(a,a)] -> [(a,a)]
listVersion = Set.toList . reflexiveClosure . Set.fromList
If any of this is unclear, please leave a comment and I will explain more in detail.

Using few functions in Haskell together

I made this code where I need to find elements in a list that appears only once
for example: for input [1,2,2,3,4,4], the output will be: [1,3]
unique :: =[a]->[a]
unique xs =[x|x<-xs, elemNum x xs ==1]
elemNum :: Int -> [Int]->[Int]
elemNum x (y:ys)
| x==y =1+ elemNum x ys
| otherwise =elemNum x ys
However I am getting an error :
Not in scope: `unique'
Is this the correct way to use 2 function in Haskell? (define them at the same file), What'a wrong with the code?
There are a few problems in your code:
type signature of unique is wrong, it should be
unique :: (Eq a) => [a] -> [a]
that type constraint (Eq a) comes from elemNum
type signature of elemNum also wrong, it should be
elemNum :: (Eq a) => a -> [a] -> Int
that type constraint comes from ==, and the type of its first parameter no need to be Int, but its return type should be Int because you want to find out how many x in xs.
Also, you forgot to deal with empty list in that definition.
Here is a fixed version of your code:
unique :: (Eq a) => [a] -> [a]
unique xs =[x| x<-xs, elemNum x xs == 1]
elemNum :: (Eq a) => a -> [a] -> Int
elemNum x [] = 0
elemNum x (y:ys)
| x==y = 1 + elemNum x ys
| otherwise = elemNum x ys
Here is another implementation:
onlyOnce [] = []
onlyOnce (x:xs)
| x `elem` xs = onlyOnce $ filter (/=x) xs
| otherwise = x : onlyOnce xs
If x occurs in xs, then the result of onlyOnce (x:xs) should be the same as the result of applying onlyOnce to the result of removing all occurrences of x from xs; otherwise, x occurs in (x:xs) only once, so x should be part of the final result.
You have an equals sign in the Type declaration for unique:
unique :: =[a]->[a]
should be
unique :: [a] -> [a]
In my opinion it is much easier to implement this function using functions from Data.List module:
import Data.List
unique :: (Ord a) => [a] -> [a]
unique = map (\(y,_) -> y) . filter (\(x,l) -> l == 1) . map (\l#(x:xs) -> (x,length l)) . group . sort

Converting Function To Maybe Type

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!

Resources