Given a data type, implement the Semigroup instance. Heres the data type I was given to implement:
data Or a b = Fst a | Snd b deriving (Eq, Show, Num)
. And it should function like so:
Prelude> Fst 1 <> Snd 2
Snd 2
Prelude> Fst 1 <> Fst 2
Fst 2
Prelude> Snd 1 <> Fst 2
Snd 1
Prelude> Snd 1 <> Snd 2
Snd 1
When I test values like > Fst "help" <> Fst "me"
it works correctly, but when I test other values I get errors. When I try to fix these errors by deriving the classes from the errors, I get more errors. What am I doing wrong here?
data Or a b =
Fst a
| Snd b
deriving (Eq, Show)
instance (Semigroup a, Semigroup b, Num a, Num b) => Semigroup (Or a b) where
(Snd a) <> _ = Snd a
_ <> (Snd a) = Snd a
(Fst a) <> (Fst b) = Fst b
When I try to test with integers > Fst 1 <> Fst 2
I get:
No instance for (Num a0) arising from a use of ‘it’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance RealFloat a => Num (Data.Complex.Complex a)
-- Defined in ‘Data.Complex’
instance Data.Fixed.HasResolution a => Num (Data.Fixed.Fixed a)
-- Defined in ‘Data.Fixed’
instance forall (k :: BOX) (f :: k -> *) (a :: k).
Num (f a) =>
Num (Data.Monoid.Alt f a)
-- Defined in ‘Data.Monoid’
...plus 21 others
In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it
When I try to derive the Num class data Or a b = Fst a | Snd b deriving (Eq, Show, Num)
I get:
Can't make a derived instance of ‘Num (Or a b)’:
‘Num’ is not a derivable class
In the data declaration for ‘Or’
Failed, modules loaded: none.
The real problem is the constraint you've put on your instance, which you don't need. Just write
instance Semigroup (Or a b) where
(Snd a) <> _ = Snd a
_ <> (Snd a) = Snd a
(Fst a) <> (Fst b) = Fst b
As chepner shows, you can actually cut down the number of lines and the number of patterns, and return one of the arguments as the result instead of constructing a new copy of it. That's potentially good for efficiency.
Less importantly, the parentheses in your patterns are all redundant, because application has higher precedence than any operator.