Haskell - Automatic Monad instance

Viewed 261

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

1 Answers

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.

Related