I'm trying to create my own data type, which will be part of Monad class, but
newtype Container a = Container a deriving Monad
gives me this error:
* Can't make a derived instance of `Monad Container'
(even with cunning GeneralizedNewtypeDeriving):
cannot eta-reduce the representation type enough
* In the newtype declaration for `Container'
|
30 | newtype Container a = Container a deriving Monad
It works fine for other classes (Show for example), but not for Monad, so how can I convince ghci to instance my Container to Monad class?
Thanks
A monad is an algebraic structure in category theory, and in Haskell it is used to describe computations as sequences of steps, and to handle side effects such as state and IO. Monads are abstract, and they have many useful concrete instances. Monads provide a way to structure a program.
In Haskell, there is an operator bind, or ( >>= ) that allows for this monadic composition in a more elegant form similar to function composition.
Lists are a fundamental part of Haskell, and we've used them extensively before getting to this chapter. The novel insight is that the list type is a monad too! As monads, lists are used to model nondeterministic computations which may return an arbitrary number of results.
The Maybe sum type is a useful data type that forms a functor. Like many other useful functors, it also forms a monad.
It works fine for other classes (Show for example)
Only a fixed set of standard classes support deriving out-of-the-box:
In Haskell 98, the only derivable classes are Eq, Ord, Enum, Ix, Bounded, Read, and Show. Various language extensions extend this list.
--- The GHC User Manual
In particular Monad
does not belong to that list, nor the extended one.
There are more extensions that generalize deriving to arbitrary classes, but they cannot be 100% automated. Someone somewhere has to specify how that deriving is to be done; depending on the class, the user may be required to carry the burden because there is information that fundamentally cannot be inferred.
In your case, the newtype Container
is representationally equivalent to the Identity
monad in the standard library, so you can use DerivingVia
:
{-# LANGUAGE DerivingVia #-}
import Data.Functor.Identity
newtype Container a = Container a deriving (Functor, Applicative, Monad) via Identity
There is only one sensible instance in this very particular situation, but most of the time it's not easy to tell what the instance should be even if there is only one.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With