I have the following newtype:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype Wrap m a = Wrap {runWrap :: m a}
deriving (Functor, Applicative, Monad, MonadTrans)
I'm trying to derive MonadTrans automatically, but I get the following error:
• Can't make a derived instance of ‘MonadTrans Wrap’
(even with cunning GeneralizedNewtypeDeriving):
cannot eta-reduce the representation type enough
• In the newtype declaration for ‘Wrap’
However, writing the trivial instance for MonadTrans works just fine:
instance MonadTrans Wrap where
lift = Wrap
What is the reason for such an error message?
GeneralizedNewtypeDeriving uses the underlying instance for a class for the implementation of the class for the newtype. However, in this case that doesn't make any sense, because m isn't of the right kind to even be an instance of MonadTrans (recall that m :: * -> *, but MonadTrans wants (* -> *) -> * -> *).
Related
Are there combinators to write Haskell types in pointfree style?
I have a type synonym that is something like:
type FooT m a = StateT State (ReaderT (Params m) m)
I'd like to be able to write the right-hand-side of this in pointfree style in order to instantiate a typeclass that demands a parameter be a monad transformer. ie, there is some typeclass like:
class (MonadTrans t, Bar (t Monad)) => Baz t where -- where Bar is some other typeclass
...
And I would like to instantiate it with my stack of transformers. However, I need to provide it with something of kind (* -> *) -> * -> *, which means I would need to write a type-level function in order to pass my StateT State (ReaderT ...) transformer as a parameter to the typeclass.
I tried using type families but it seems like they need to be fully applied.
You must use newtype. Type synonyms have to be fully applied, so they do not actually give you a way to rearrange type expressions to fit certain kinds.
The simplest is to turn FooT into a newtype:
newtype FooT m a = FooT (StateT State (ReaderT (Params m) m) a)
It's possible to develop a combinator style, but every combinator must be a newtype so that's kind of a pain to unwrap.
{-# LANGUAGE PolyKinds, TypeOperators #-}
newtype (:.:) f g a = (:.:) (f (g a))
newtype Join f a = Join (f a a)
type FooT = StateT State :.: Join (ReaderT :.: Params)
-- Good luck untangling that.
I may be naive in my thinking here but I think if the right hand value of a Reader is an instance of Monoid then a Monoid could be defined for Reader... Here is my implementation:
instance Monoid a => Monoid (Reader r a) where
mempty = pure mempty
mappend ra rb = (<>) <$> ra <*> rb
This however results in the following error:
• Illegal instance declaration for ‘Monoid (Reader r a)’
(All instance types must be of the form (T t1 ... tn)
where T is not a synonym.
Use TypeSynonymInstances if you want to disable this.)
• In the instance declaration for ‘Monoid (Reader r a)’
|
413 | instance Monoid a => Monoid (Reader r a) where
| ^^^^^^^^^^^^^^^^^^^
I am unsure what this error actually means, and why I am unable to implement Monoid for Reader though I presume it is something to do with Reader being a higher kinded type?
There are two problems. The first is this:
type Reader r = ReaderT r Identity
For historical reasons, type synonyms are not allowed in instance declarations. This is the
where T is not a synonym.
part of the error. Luckily we can just expand the synonym; this would give us
instance Monoid a => Monoid (ReaderT r Identity a)
but now we would fall afowl of the other part of the error, namely:
All instance types must be of the form (T t1 ... tn)
Specifically, Identity is not a type variable, so it doesn't fit this form. Again this restriction is in place primarily for historical reasons. You can remove both restrictions by enabling two language extensions:
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
However, in this case it's not needed. The preferable way is to actually use the prescribed form of instance declaration, so:
instance (Applicative f, Monoid m) => Monoid (ReaderT r f m) where
mempty = pure mempty
mappend = liftA2 mappend
This requires no extensions, and works not just for Reader but for ReaderT transforming any Applicative instance.
However it does make an orphan instance; hence you should consider writing another newtype wrapper.
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-- or, instead of GeneralizedNewtypeDeriving, write the obvious instances by hand
newtype App f m = App { getApp :: f m } deriving (Functor, Applicative)
instance (Applicative f, Monoid m) => Monoid (App f m) where
mempty = pure mempty
mappend = liftA2 mappend
Then you can use App (Reader r) a as a monoid whenever a is a monoid. I seem to recall this existed somewhere in the standard libraries already, but I can't find it any more...
The issue here is that your Reader is a type alias instead of a newtype.
Using the former is disallowed by Haskell2010 (which is very conservative in what it is allowed), but GHC allows using type aliases in instances if you turn on the extension reported in the error you posted. Note that in such case it would define an instance for the expansion of the alias, e.g.
instance Monoid a => Monoid (r -> a) where ...
For a Reader type, I'd prefer to use a newtype, even if one needs to wrap/unwrap it when it is used.
I'm having trouble deriving a Typeable1 instance for a date structure in Haskell.
This is my code:
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE DeriveDataTypeable #-}
import Data.Typeable (Typeable,Typeable1)
newtype FooM m a = Foo { unFoo :: (a -> Bar m) -> Bar m }
newtype Bar m = Atom (m (Maybe (Bar m)))
type Baz m = Waldo (FooM m ())
type Waldo a = a
data Qux m = Qux {
baz :: Baz m
, num :: Int
} -- deriving Typeable1 [1]
-- deriving instance Typeable1 Qux [2]
Uncommenting the first comment [1] gives this error:
Cannot derive well-kinded instance of form `Typeable1 (Qux ...)'
Class `Typeable1' expects an argument of kind `* -> *'
In the data type declaration for `Qux'
And uncommenting [2] gives this error:
Kind mis-match
The first argument of `Typeable1' should have kind `* -> *',
but `Qux' has kind `(* -> *) -> *'
In the stand-alone deriving instance for `Typeable1 Qux'
My question is: How can I add a Typeable/Typeable1 instance of Qux, please?
You can't make Qux an instance of Typeable1, but in modern GHC, you should be able to derive an instance of Typeable, which is now kind-polymorphic enough to handle such higher-kinded types, making Typeable1 and its ilk unnecessary.
Outdated answer, kept because it was the accepted answer when the question was asked: Unfortunately, you can't: the Typeable hierarchy doesn't have any typeclasses for things of kind (* -> *) -> *. This may be fixed at some future time now that GHC is starting to support kind polymorphism.
It was appear that this problem is currently being considered in the ghc ticket, #5391. So there's a chance that the deriving Typeable problem will go away in GHC 7.6.
Question. Is there any way to make this code work without an explicit type signature?
Code. First, I have a in-practice-much-nicer alternate MonadTrans class, inspired by Data.Newtype. It looks like this,
{-# LANGUAGE FlexibleContexts, TypeFamilies #-}
module Alt.Control.Monad.Trans where
import Control.Monad
class (Monad 𝔪, Monad (BaseMonad 𝔪)) => MonadTrans (𝔪 :: * -> *) where
type BaseMonad 𝔪 :: * -> *
lift :: (BaseMonad 𝔪) α -> 𝔪 α
Then, I have a class A with method foo, and if some base monad M is an A, then any transformed monad T M is also an A. In code,
class A 𝔪 where
foo :: String -> 𝔪 ()
instance (A (BaseMonad 𝔪), MonadTrans 𝔪) => A 𝔪 where
foo n = lift $ foo n
However, if I now want to create a shortcut for foo with its first argument substituted, then I need an explicit type signature, or the compiler's context stack overflows.
minimize_call :: A 𝔪 => 𝔪 ()
minimize_call = foo "minimize"
Possible info to help inference. Let's say we have an associated type B :: * -> *. I'm thinking that I want to tell the compiler B satisfies B t /= t, B (B t) /= B t, etc. i.e. B is somehow "monotonic" -- that chasing associated types is equivalent to removing newtype wrappers, and it should know that it cannot remove newtype wrappers forever, hence adding the context A to the signature is necessary.
Yes, there is a way. Provide a grounded instance for A, and add NoMonomorphismRestriction to the language pragma (in addition to the also required FlexibleInstances and UndecidableInstances).
However, the A class will be unusable. There is no way for the compiler to know that there never will be a MonadTrans instance with BaseMonad m = m. Thus it cannot select an instance, ever, because it cannot know whether to use the instance from here or another one.
{-# LANGUAGE FlexibleContexts, TypeFamilies, FlexibleInstances, UndecidableInstances, NoMonomorphismRestriction #-}
module Trans (MonadTrans(..), A(..), minimize_call) where
import Control.Monad
class (Monad m, Monad (BaseMonad m)) => MonadTrans (m :: * -> *) where
type BaseMonad m :: * -> *
lift :: (BaseMonad m) α -> m α
class A m where
foo :: String -> m ()
data Foo a = Bork
instance Monad Foo where
return _ = Bork
_ >>= _ = Bork
instance A Foo where
foo _ = Bork
instance (A (BaseMonad m), MonadTrans m) => A m where
foo n = lift $ foo n
-- minimize_call :: A m => m ()
minimize_call = foo "minimize"
compiles with ghc 6.12, 7.0, 7.2 and 7.4. Without the signature, minimize_call must get a monomorphic type, unless the MR is turned off. That can't work anyway because the constraint A m is not defaultable. So therefore the MR must be turned off. But then the type checker still chases its own tail trying to prove the constraint is satisfiable. With only the lifting instance, it can't. If you provide an anchor, it can.
But providing a type signature is much much better.
Consider the following example program:
next :: Int -> Int
next i
| 0 == m2 = d2
| otherwise = 3 * i + 1
where
(d2, m2) = i `divMod` 2
loopIteration :: MaybeT (StateT Int IO) ()
loopIteration = do
i <- get
guard $ i > 1
liftIO $ print i
modify next
main :: IO ()
main = do
(`runStateT` 31) . runMaybeT . forever $ loopIteration
return ()
It can only use get instead of lift get because instance MonadState s m => MonadState s (MaybeT m) is defined in the MaybeT module.
Many such instances are defined in kind of a combinatoric explosion manner.
It would have been nice (although impossible? why?) if we had the following type-class:
{-# LANGUAGE MultiParamTypeClasses #-}
class SuperMonad m s where
lifts :: m a -> s a
Let's try to define it as such:
{-# LANGUAGE FlexibleInstances, ... #-}
instance SuperMonad a a where
lifts = id
instance (SuperMonad a b, MonadTrans t, Monad b) => SuperMonad a (t b) where
lifts = lift . lifts
Using lifts $ print i instead of liftIO $ print i works, which is nice.
But using lifts (get :: StateT Int IO Int) instead of (get :: MaybeT (StateT Int IO) Int) doesn't work.
GHC (6.10.3) gives the following error:
Overlapping instances for SuperMonad
(StateT Int IO) (StateT Int IO)
arising from a use of `lifts'
Matching instances:
instance SuperMonad a a
instance (SuperMonad a b, MonadTrans t, Monad b) =>
SuperMonad a (t b)
In a stmt of a 'do' expression:
i <- lifts (get :: StateT Int IO Int)
I can see why "instance SuperMonad a a" applies. But why does GHC think that the other one does, too?
To follow up ephemient's excellent answer: Haskell type classes use an open-world assumption: some idiot can come along later and add an instance declaration that's not a duplicate and yet overlaps with your instance. Think of it as an adversary game: if an adversary can make your program ambiguous, the compiler bleats.
If you're using GHC you can of course say to the compiler "to hell with your paranoia; allow me my ambiguous instance declaration":
{-# LANGUAGE OverlappingInstances #-}
If later evolution of your program leads to overload resolution you didn't expect, the compiler gets 1,000 I-told-you-so points :-)
Deprecation Note
This pragma has been deprecated since GHC 7.10, and per-instance pragmas should be used instead. More detail can be found in the GHC documentation.
Just because you haven't defined an instance in your current module doesn't mean that one couldn't be defined somewhere else.
{-# LANGUAGE ... #-}
module SomeOtherModule where
-- no practical implementation, but the instance could still be declared
instance SuperMonad (StateT s m) m
Suppose your module and SomeOtherModule are linked together in a single program.
Now, answer this: does your code use
instance SuperMonad a a
-- with a = StateT Int IO
or
instance (SuperMonad a b, MonadTrans t, Monad b) => SuperMonad a (t b)
-- with a = StateT Int IO
-- t = StateT Int
-- b = IO
?
When you have overlapping instances try to attach their behaviour to newtypes:
type SuperEgo :: (k -> Type) -> (k -> Type)
newtype SuperEgo m a = SuperEgo (m a)
type Elevator :: (k -> k1 -> Type) -> (k -> k1 -> Type)
newtype Elevator trans m a = Elevator (trans m a)
instance SuperMonad m (SuperEgo m) where
lifts :: m ~> SuperEgo m
lifts = SuperEgo
instance (SuperMonad m super, Monad super, MonadTrans trans) => SuperMonad m (Elevator trans super) where
lifts :: m ~> Elevator trans super
lifts = Elevator . lift . lifts
Monads can now derive via SuperEgo M to get an identity instances
{-# Language DerivingVia #-}
data Ok a = Ok a
deriving (SuperMonad Ok)
via SuperEgo Ok
It's more of a hassle to define a monad transformer so I'll show how to define a lifting instance for an existing Monad transformers like StateT s. This uses standalone deriving which is more verbose, you need to fill in the class context yourself:
deriving
via Elevator (StateT s) super
instance (Monad super, SuperMonad m super) => SuperMonad m (StateT s super)