Haskell - create instance of class (how to do it right?) - haskell

I read the chapter about that topic in "learn you a haskell" and tried to find some hints on different websites - but are still unable to solve the following task.
Im a haskell newbie (6 weeks of "experience") and its the first time I have to work with instances.
So here is the task, my code has to pass the HUnit tests and the end. I tried to implement the instances but it seems like I´ve missed something there. Hope you can help me! THX
module SemiGroup where
{-
A type class 'SemiGroup' is given. It has exactly one method: a binary operation
called '(<>)'. Also a data type 'Tree' a newtype 'Sum' and a newtype 'Max' are
given. Make them instances of the 'SemiGroup' class.
The 'Tree' instance should build a 'Branch' of the given left and right side.
The 'Sum' instance should take the sum of its given left and right side. You need
a 'Num' constraint for that.
The 'Max' instance should take the maximum of its given left and right side. You
also need a constraint for that but you have to figure out yourself which one.
This module is not going to compile until you add the missing instances.
-}
import Test.HUnit (runTestTT,Test(TestLabel,TestList),(~?=))
-- | A semigroup has a binary operation.
class SemiGroup a where
(<>) :: a -> a -> a
-- Leaf = Blatt, Branch = Ast
-- | A binary tree data type.
data Tree a = Leaf a
| Branch (Tree a) (Tree a)
deriving (Eq,Show)
-- | A newtype for taking the sum.
newtype Sum a = Sum {unSum :: a}
-- | A newtype for taking the maximum.
newtype Max a = Max {unMax :: a}
instance SemiGroup Tree where
(<>) x y = ((x) (y))
instance SemiGroup (Num Sum) where
(<>) x y = x+y
instance SemiGroup (Eq Max) where
(<>) x y = if x>y then x else y
-- | Tests the implementation of the 'SemiGroup' instances.
main :: IO ()
main = do
testresults <- runTestTT tests
print testresults
-- | List of tests for the 'SemiGroup' instances.
tests :: Test
tests = TestLabel "SemiGroupTests" (TestList [
Leaf "Hello" <> Leaf "Friend" ~?= Branch (Leaf "Hello") (Leaf "Friend"),
unSum (Sum 4 <> Sum 8) ~?= 12,
unMax (Max 8 <> Max 4) ~?= 8])
I tried something like:
class SemiGroup a where
(<>) :: a -> a -> a
-- Leaf = Blatt, Branch = Ast
-- | A binary tree data type.
data Tree a = Leaf a
| Branch (Tree a) (Tree a)
deriving (Eq,Show)
-- | A newtype for taking the sum.
newtype Sum a = Sum {unSum :: a}
-- | A newtype for taking the maximum.
newtype Max a = Max {unMax :: a}
instance SemiGroup Tree where
x <> y = Branch x y
instance Num a => SemiGroup (Sum a) where
x <> y = x+y
instance Eq a => SemiGroup (Max a) where
x <> y = if x>y then x else y
But there a still some failures left! At least the wrap/unwrap thing that "chi" mentioned. But I have no idea. maybe another hint ? :/

I fail to see how to turn Tree a into a semigroup (unless it has to be considered up-to something).
For the Sum a newtype, you need to require that a is of class Num. Then, you need to wrap/unwrap the Sum constructor around values so that: 1) you take two Sum a, 2) you convert them into two a, which is a proper type over which + is defined, 3) you sum them, 4) you turn the result back into a Sum a.
You can try to code the above yourself starting from
instance Num a => Semigroup (Sum a) where
x <> y = ... -- Here both x and y have type (Sum a)
The Max a instance will require a similar wrap/unwrap code.
A further hint: to unwrap a Sum a into an a you can use the function
unSum :: Sum a -> a
to wrap an a into a Sum a you can use instead
Sum :: a -> Sum a
Note that both functions Sum, unSum are already implicitly defined by your newtype declaration, so you do not have to define them (you already did).
Alternatively, you can use pattern matching to unwrap your values. Instead of defining
x <> y = ... -- x,y have type Sum a (they are wrapped)
you can write
Sum x <> Sum y = ... -- x,y have type a (they are unwrapped)

Pay attention to the types. Either manually, or with some help from GHCi, figure out the type of the functions you are writing -- you'll find they don't match the types that the typeclass instance needs. You'll use wrapping and unwrapping to adjust the types until they work.

Related

Haskell nested lists with newtype

Disclaimer: I am new to working with haskell.
I am working with proving logical formulas in haskell. I have trouble understanding how to work with newtypes and datas properly.
I have defined the following types to represent logical formulas that have the structure: (a or b or c) and (d or e) and (f) etc.
data Literal x = Literal x | Negation x
deriving (Show, Eq)
newtype Or x = Or [Literal x]
deriving (Show, Eq)
newtype And x = And [Or x]
deriving (Show, Eq)
I want to write a function that can filter on the literals (i.e. take out certain a b or c based on some condition). Naively I thought this should be similar to filtering on [[Literal x]] but I cannot seem to get it to work.
My current method is something like:
filterLit :: Eq x => And x -> And x
filterLit = map (\(Or x) -> (filter (\(Lit l) -> condition l) x))
This doesn't type. I feel like I'm missing some syntax rules here. Let me know if you have suggestions on how I should approach it.
\(Or x) -> filter (\(Lit l) -> condition l) x
Let's check the type of this function.
The domain must have type Or x. That's OK.
The codomain is the result of filter, hence it is a list. Let's only write [....] for that.
Hence, the function is Or x -> [....].
If we map that, we get [Or x] -> [[....]]. This is not the same as the claimed type And x -> And x -- a type error is raised.
First, you want your lambda to have type Or x -> Or x. For that, you can use \(Or x) -> Or (filter .....).
Then, you want filterLit to be something like
filterLit (And ys) = And (map ....)
so that it has the right type.

Can you determine the min or max of a list using only the list monad?

Trying to understand the relation between Monad and Foldable. I am aware that that part of the value of the Monad, Applicative and Functor typeclasses is their ability to lift functions over structure, but what if I wanted to generate a summary value (e.g. min or max) for the values contained in a Monad?
This would be impossible without an accumulator right (like in foldable)? And to have an accumulator you have to inject or destroy structure?
min :: Ord a => a -> a -> a
foldMin :: (Foldable t, Ord a) => t a -> Maybe a
foldMin t = foldr go Nothing t
where
go x Nothing = Just x
go x (Just y) = Just (min x y)
Here, the Nothing value is the accumulator. So it would not be possible to do an operation that produces a summary value like this within the confines of a do block?
I'm not entirely sure I understand the question, so forgive me if this isn't a useful answer, but as I understand it, the core of the question is this:
So it would not be possible to do an operation that produces a summary value like this within the confines of a do block?
Correct, that would not be possible. Haskell's do notation is syntactic sugar over Monad, so basically syntactic sugar over >>= and return.
return, as you know, doesn't let you 'access' the contents of the Monad, so the only access to the contents you have is via >>=, and in the case of the list monad, for instance, that only gives you one value at a time.
Notice that Foldable doesn't even require that the data container is a Functor (much less a Monad). Famously, Set isn't a Functor instance, but it is a Foldable instance.
You can, for example, find the minimum value in a set:
Prelude Data.Foldable Set> foldr (\x -> Just . maybe x (min x)) Nothing $ Set.fromList [42, 1337, 90125, 2112]
Just 42
The contrived and inefficient code below is the closest I can get to "using only the list monad". This is probably not what the OP is looking for, but here it is.
I also exploit head (which you can replace with listToMaybe, if we want totality), and null. I also use empty (which you can replace with []).
The code works by non deterministically picking an element m and then checking that no greater elements exist. This has a quadratic complexity.
import Control.Applicative
maximum :: Ord a => [a] -> a
maximum xs = head maxima
where
isMax m = null $ do
x <- xs
if x > m
then return x
else empty
maxima = do
m <- xs -- non deterministically pick a maximum
if isMax m
then return m
else empty
I'm also not sure, what the actual question ist, but the need for an accumulator can be hidden with a Monoid instance. Then - for your minimum example - you can use use foldMap from Data.Foldable to map and merge all values of your Foldable. E.g.:
data Min a = Min { getMin :: Maybe a } deriving Show
instance Ord a => Monoid (Min a) where
mempty = Min Nothing
mappend a (Min Nothing) = a
mappend (Min Nothing) b = b
mappend (Min (Just a)) (Min (Just b)) = Min (Just (min a b))
foldMin :: (Foldable t, Ord a) => t a -> Maybe a
foldMin = getMin . foldMap (Min . Just)

Generic solution to (Eq, Show) overlapping instances issue when defining class (* -> *)

Stack has many threads on overlapping instances, and while these are helpful in explaining the source of the problem, I am still not clear as to how to redesign my code for the problem to go away. While I will certain invest more time and effort in going through the details of existing answers, I will post here the general pattern which I have identified as creating the problem, in the hope that a simple and generic answer exists: I typically find myself defining a class such as:
{-# LANGUAGE FlexibleInstances #-}
class M m where
foo :: m v -> Int
bar :: m v -> String
together with the instance declarations:
instance (M m) => Eq (m v) where
(==) x y = (foo x) == (foo y) -- details unimportant
instance (M m) => Show (m v) where
show = bar -- details unimportant
and in the course of my work I will inevitably create some data type:
data A v = A v
and declare A as an instance of class M:
instance M A where
foo x = 1 -- details unimportant
bar x = "bar"
Then defining some elements of A Integer:
x = A 2
y = A 3
I have no issue printing x and y or evaluating the Boolean x == y, but if I attempt to print the list [x] or evaluate the Boolean [x] == [y], then the overlapping instance error occurs:
main = do
print x -- fine
print y -- fine
print (x == y) -- fine
print [x] -- overlapping instance error
if [x] == [y] then return () else return () -- overlapping instance error
The cause of these errors is now very clear I think: they stem from the existing instance declarations instance Show a => Show [a] and instance Eq a => Eq [a] and while it is true that [] :: * -> * has not yet been declared as an instance of my class M, there is nothing preventing someone doing so at some point: so the compiler ignores the context of instance declarations.
When faced with the pattern I have described, how can it be re-engineered to avoid the problem?
There's no backtracking in instance search. Instances are matched purely based on the syntactic structure of the instance head. That means instance contexts are not accounted for during instance resolution.
So, when you write
instance (M m) => Show (m v) where
show = bar
you're saying "Here is an instance for Show, for any type of the form m v". Since [x] :: [] (A Int) is indeed a type of the form m v (set m ~ [] and v ~ A Int), instance search for Show [A Int] turns up two candidates:
instance Show a => Show [a]
instance M m => Show (m v)
Like I said, the type checker doesn't look at the instances' contexts when selecting an instance, so these two instances are overlapping.
The fix is to not declare instances like Show (m v). As a general rule, it's a bad idea to declare instances whose head is composed purely of type variables. Every instance you write should start with an honest-to-goodness type constructor, and you should approach instances which don't fit that pattern with suspicion.
Supplying a newtype for your default instances is a fairly standard design (see, for example, WrappedBifunctor's Functor instance),
newtype WrappedM m a = WrappedM { unwrapM :: m a }
instance M m => Show (WrappedM m a) where
show = bar . unwrapM
as is giving a default implementation of the function at the top level (see eg foldMapDefault):
showDefault = bar

newtype v. data for Monoid Wrappers? [duplicate]

When looking at Data.Monoid, I see there are various newtype wrappers, such as All, Sum, or Product, which encode various kinds of monoids. However, when trying to use those wrappers, I can't help but wonder what's the benefit over using their non-Data.Monoid counterparts. For instance, compare the rather cumbersome summation
print $ getSum $ mconcat [ Sum 33, Sum 2, Sum 55 ]
vs. the more succinct idiomatic variant
print $ sum [ 33, 2, 55 ]
But what's the point? Is there any practical value having all those newtype wrappers? Are there more convincing examples of Monoid newtype wrapper usage than the one above?
Monoid newtypes: A zero space no-op to tell the compiler what to do
Monoids are great to wrap an existing data type in a new type to tell the compiler what operation you want to do.
Since they're newtypes, they don't take any additional space and applying Sum or getSum is a no-op.
Example: Monoids in Foldable
There's more than one way to generalise foldr (see this very good question for the most general fold, and this question if you like the tree examples below but want to see a most general fold for trees).
One useful way (not the most general way, but definitely useful) is to say something's foldable if you can combine its elements into one with a binary operation and a start/identity element. That's the point of the Foldable typeclass.
Instead of explicitly passing in a binary operation and start element, Foldable just asks that the element data type is an instance of Monoid.
At first sight this seems frustrating because we can only use one binary operation per data type - but should we use (+) and 0 for Int and take sums but never products, or the other way round? Perhaps should we use ((+),0) for Int and (*),1 for Integer and convert when we want the other operation? Wouldn't that waste a lot of precious processor cycles?
Monoids to the rescue
All we need to do is tag with Sum if we want to add, tag with Product if we want to multiply, or even tag with a hand-rolled newtype if we want to do something different.
Let's fold some trees! We'll need
fold :: (Foldable t, Monoid m) => t m -> m
-- if the element type is already a monoid
foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m
-- if you need to map a function onto the elements first
The DeriveFunctor and DeriveFoldable extensions ({-# LANGUAGE DeriveFunctor, DeriveFoldable #-}) are great if you want to map over and fold up your own ADT without writing the tedious instances yourself.
import Data.Monoid
import Data.Foldable
import Data.Tree
import Data.Tree.Pretty -- from the pretty-tree package
see :: Show a => Tree a -> IO ()
see = putStrLn.drawVerticalTree.fmap show
numTree :: Num a => Tree a
numTree = Node 3 [Node 2 [],Node 5 [Node 2 [],Node 1 []],Node 10 []]
familyTree = Node " Grandmama " [Node " Uncle Fester " [Node " Cousin It " []],
Node " Gomez - Morticia " [Node " Wednesday " [],
Node " Pugsley " []]]
Example usage
Strings are already a monoid using (++) and [], so we can fold with them, but numbers aren't, so we'll tag them using foldMap.
ghci> see familyTree
" Grandmama "
|
----------------------
/ \
" Uncle Fester " " Gomez - Morticia "
| |
" Cousin It " -------------
/ \
" Wednesday " " Pugsley "
ghci> fold familyTree
" Grandmama Uncle Fester Cousin It Gomez - Morticia Wednesday Pugsley "
ghci> see numTree
3
|
--------
/ | \
2 5 10
|
--
/ \
2 1
ghci> getSum $ foldMap Sum numTree
23
ghci> getProduct $ foldMap Product numTree
600
ghci> getAll $ foldMap (All.(<= 10)) numTree
True
ghci> getAny $ foldMap (Any.(> 50)) numTree
False
Roll your own Monoid
But what if we wanted to find the maximum element? We can define our own monoids. I'm not sure why Max (and Min) aren't in. Maybe it's because no-one likes thinking about Int being bounded or they just don't like an identity element that's based on an implementation detail. In any case here it is:
newtype Max a = Max {getMax :: a}
instance (Ord a,Bounded a) => Monoid (Max a) where
mempty = Max minBound
mappend (Max a) (Max b) = Max $ if a >= b then a else b
ghci> getMax $ foldMap Max numTree :: Int -- Int to get Bounded instance
10
Conclusion
We can use newtype Monoid wrappers to tell the compiler which way to combine things in pairs.
The tags do nothing, but show what combining function to use.
It's like passing the functions in as an implicit parameter rather than an explicit one (because that's kind of what a type class does anyway).
How about in an instance like this:
myData :: [(Sum Integer, Product Double)]
myData = zip (map Sum [1..100]) (map Product [0.01,0.02..])
main = print $ mconcat myData
Or without the newtype wrapper and the Monoid instance:
myData :: [(Integer, Double)]
myData = zip [1..100] [0.01,0.02..]
main = print $ foldr (\(i, d) (accI, accD) -> (i + accI, d * accD)) (0, 1) myData
This is due to the fact that (Monoid a, Monoid b) => Monoid (a, b). Now, what if you had custom data types and you wanted to fold over a tuple of these values applying a binary operation? You could simply write a newtype wrapper and make it an instance of Monoid with that operation, construct your list of tuples, then just use mconcat to fold across them. There are many other functions that work on Monoids as well, not just mconcat, so there are certainly a myriad of applications.
You could also look at the First and Last newtype wrappers for Maybe a, I can think of many uses for those. The Endo wrapper is nice if you need to compose a lot of functions, the Any and All wrappers are good for working with booleans.
Suppose you are working in the Writer monad and you want to store the sum of everything you tell. In that case you would need the newtype wrapper.
You would also need the newtype to use functions like foldMap that have a Monoid constraint.
The ala and alaf combinators from Control.Lens.Wrapped in the lens package can make working with these newtypes more pleasant. From the documentation:
>>> alaf Sum foldMap length ["hello","world"]
10
>>> ala Sum foldMap [1,2,3,4]
10
Sometimes you just end up needing a particular Monoid to fill a type constraint. One place that shows up sometimes is that Const has an Applicative instance iff it stores a Monoid.
instance Monoid m => Applicative (Const m) where
pure _ = Const mempty
Const a <*> Const b = Const (a <> b)
That's obviously a bit bizarre, but sometimes it's what you need. The best example I know is in lens where you end up with types like
type Traversal s a = forall f . Applicative f => (a -> f a) -> (s -> f s)
If you specialize f to something like Const First using the Monoid newtype First
newtype First a = First { getFirst :: Maybe a }
-- Retains the first, leftmost 'Just'
instance Monoid (First a) where
mempty = First Nothing
mappend (First Nothing) (First Nothing) = First Nothing
mappend (First (Just x)) _ = First (Just x)
then we can interpret that type
(a -> Const (First a) a) -> (s -> Const (First a) s)
as scanning through s and picking up the first a inside of it.
So, while that's a really specific answer the broad response is that it's sometimes useful to be able to talk about a bunch of different default Monoid behaviors. Somebody had to write all the obvious Monoid behaviors, anyway, and they might as well be put in Data.Monoid.
The basic idea, I think, is that you can have something like
reduce = foldl (<>) mempty
and it'll work for any list of those wrapped things.

Sort by constructor ignoring (part of) value

Suppose I have
data Foo = A String Int | B Int
I want to take an xs :: [Foo] and sort it such that all the As are at the beginning, sorted by their strings, but with the ints in the order they appeared in the list, and then have all the Bs at the end, in the same order they appeared.
In particular, I want to create a new list containg the first A of each string and the first B.
I did this by defining a function taking Foos to (Int, String)s and using sortBy and groupBy.
Is there a cleaner way to do this? Preferably one that generalizes to at least 10 constructors.
Typeable, maybe? Something else that's nicer?
EDIT: This is used for processing a list of Foos that is used elsewhere. There is already an Ord instance which is the normal ordering.
You can use
sortBy (comparing foo)
where foo is a function that extracts the interesting parts into something comparable (e.g. Ints).
In the example, since you want the As sorted by their Strings, a mapping to Int with the desired properties would be too complicated, so we use a compound target type.
foo (A s _) = (0,s)
foo (B _) = (1,"")
would be a possible helper. This is more or less equivalent to Tikhon Jelvis' suggestion, but it leaves space for the natural Ord instance.
To make it easier to build comparison function for ADTs with large number of constructors, you can map values to their constructor index with SYB:
{-# LANGUAGE DeriveDataTypeable #-}
import Data.Generics
data Foo = A String Int | B Int deriving (Show, Eq, Typeable, Data)
cIndex :: Data a => a -> Int
cIndex = constrIndex . toConstr
Example:
*Main Data.Generics> cIndex $ A "foo" 42
1
*Main Data.Generics> cIndex $ B 0
2
Edit:After re-reading your question, I think the best option is to make Foo an instance of Ord. I do not think there is any way to do this automatically that will act the way you want (just using deriving will create different behavior).
Once Foo is an instance of Ord, you can just use sort from Data.List.
In your exact example, you can do something like this:
data Foo = A String Int | B Int deriving (Eq)
instance Ord Foo where
(A _ _) <= (B _) = True
(A s _) <= (A s' _) = s <= s'
(B _) <= (B _) = True
When something is an instance of Ord, it means the data type has some ordering. Once we know how to order something, we can use a bunch of existing functions (like sort) on it and it will behave how you want. Anything in Ord has to be part of Eq, which is what the deriving (Eq) bit does automatically.
You can also derive Ord. However, the behavior will not be exactly what you want--it will order by all of the fields if it has to (e.g. it will put As with the same string in order by their integers).
Further edit: I was thinking about it some more and realized my solution is probably semantically wrong.
An Ord instance is a statement about your whole data type. For example, I'm saying that Bs are always equal with each other when the derived Eq instance says otherwise.
If the data your representing always behaves like this (that is, Bs are all equal and As with the same string are all equal) then an Ord instance makes sense. Otherwise, you should not actually do this.
However, you can do something almost exactly like this: write your own special compare function (Foo -> Foo -> Ordering) that encapsulates exactly what you want to do then use sortBy. This properly codifies that your particular sorting is special rather than the natural ordering of the data type.
You could use some template haskell to fill in the missing transitive cases. The mkTransitiveLt creates the transitive closure of the given cases (if you order them least to greatest). This gives you a working less-than, which can be turned into a function that returns an Ordering.
{-# LANGUAGE TemplateHaskell #-}
import MkTransitiveLt
import Data.List (sortBy)
data Foo = A String Int | B Int | C | D | E deriving(Show)
cmp a b = $(mkTransitiveLt [|
case (a, b) of
(A _ _, B _) -> True
(B _, C) -> True
(C, D) -> True
(D, E) -> True
(A s _, A s' _) -> s < s'
otherwise -> False|])
lt2Ord f a b =
case (f a b, f b a) of
(True, _) -> LT
(_, True) -> GT
otherwise -> EQ
main = print $ sortBy (lt2Ord cmp) [A "Z" 1, A "A" 1, B 1, A "A" 0, C]
Generates:
[A "A" 1,A "A" 0,A "Z" 1,B 1,C]
mkTransitiveLt must be defined in a separate module:
module MkTransitiveLt (mkTransitiveLt)
where
import Language.Haskell.TH
mkTransitiveLt :: ExpQ -> ExpQ
mkTransitiveLt eq = do
CaseE e ms <- eq
return . CaseE e . reverse . foldl go [] $ ms
where
go ms m#(Match (TupP [a, b]) body decls) = (m:ms) ++
[Match (TupP [x, b]) body decls | Match (TupP [x, y]) _ _ <- ms, y == a]
go ms m = m:ms

Resources