Using -XGeneralizedNewtypeDeriving with -XMultiParamTypeClasses - haskell

The following code results in an error:
{-# LANGUAGE GeneralizedNewtypeDeriving, MultiParamTypeClasses, StandaloneDeriving #-}
class Module a b where
(*>) :: a -> b -> b
data D
newtype DWrapper = DW D
instance Module D D
deriving instance Module DWrapper DWrapper
The error:
No instance for (Module DWrapper D) arising from a use of ‘Main.*>’
In the first argument of ‘GHC.Prim.coerce’, namely
‘(Main.*>) :: DWrapper -> D -> D’
In the expression:
GHC.Prim.coerce ((Main.*>) :: DWrapper -> D -> D) ::
DWrapper -> DWrapper -> DWrapper
In an equation for ‘*>’:
(*>)
= GHC.Prim.coerce ((Main.*>) :: DWrapper -> D -> D) ::
DWrapper -> DWrapper -> DWrapper
When typechecking the code for ‘Main.*>’
in a derived instance for ‘Module DWrapper DWrapper’:
To see the code I am typechecking, use -ddump-deriv
So GHC is looking for a Module DWrapper D instance to derive the requested Module D D instance. This is reasonable I guess, but not what I intended. Is there a way to tell GHC which instance to derive from? How does GNTD work on MPTCs?

Unfortunately, GeneralizedNewtypeDeriving only works on the last parameter of a multi-parameter typeclass. Even with standalone deriving:
The stand-alone syntax is generalised for newtypes in exactly the same way that ordinary deriving clauses are generalised (Section 7.5.5, “Generalised derived instances for newtypes”). For example:
newtype Foo a = MkFoo (State Int a)
deriving instance MonadState Int Foo
GHC always treats the last parameter of the instance (Foo in this example) as the type whose instance is being derived.
(BTW, I tried searching for any relevant GHC trac bug report or feature request, but couldn't find any.)

Related

Compilation error with a class constraint on a phantom type in a default method

This (somewhat nonsensical) module compiles:
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ExplicitForAll #-}
module Foo where
class A t where
f :: forall x m. Monoid x => t m -> m
f = undefined
instance A [] where
f = undefined
If I remove the instance's definition of f, I would expect it to inherit the method default and amount to the same thing.
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ExplicitForAll #-}
module Foo where
class A t where
f :: forall x m. Monoid x => t m -> m
f = undefined
instance A [] where
This does not work, however. GHC 8.0.2 gives this error:
• Could not deduce (Monoid x0)
arising from a use of ‘Foo.$dmf’
from the context: Monoid x
bound by the type signature for:
f :: Monoid x => [m] -> m
at src/Foo.hs:10:10-13
The type variable ‘x0’ is ambiguous
These potential instances exist:
instance Monoid a => Monoid (IO a) -- Defined in ‘GHC.Base’
instance Monoid Ordering -- Defined in ‘GHC.Base’
instance Monoid a => Monoid (Maybe a) -- Defined in ‘GHC.Base’
...plus 7 others
(use -fprint-potential-instances to see them all)
• In the expression: Foo.$dmf #[]
In an equation for ‘f’: f = Foo.$dmf #[]
In the instance declaration for ‘A []’
I'm not sure how to read this error, because I don't know where the imaginary x0 is being inserted. Why doesn't the second example compile?
GHC is basically converting your code to this:
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ExplicitForAll #-}
module Foo where
defaultF :: forall t x m. (A t, Monoid x) => t m -> m
defaultF = undefined
class A t where
f :: forall x m. Monoid x => t m -> m
f = defaultF #t #x #m
instance A [] where
f = defaultF #[]
Now, in the last line the type variable x is not in scope since we do not have an explicit forall x. Even if it were, it is not passed to defaultF as an explicit type argument. So, the last defaultF call could be made on any monoid at all, possibly another one!
For that call, the inference engine generates a fresh x0 type variable, hence the type error message :-(
Maybe GHC's instance deriving mechanism should be updated, now that ambiguous types are allowed (which is a good thing, IMO).
For a simpler case, consider
a :: forall x. Monoid x => Int
a = undefined
b :: forall x. Monoid x => Int
b = a
The last call needs a disambiguating explicit type argument, in Haskell. It would work fine in dependently typed languages like Agda/Idris/Coq/... since these (by default, at least) pass their type arguments explicitly.

Illegal polymorphic or qualified type in typeclass

The following file Poly.hs file
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE RankNTypes #-}
module Poly () where
type ListModifier s = forall a. s -> [a] -> [a]
instance Monoid (ListModifier s) where
mempty = const id
mappend f g st = f st . g st
Gets the typechecker to complain:
Poly.hs:8:10: Illegal polymorphic or qualified type: ListModifier s …
In the instance declaration for ‘Monoid (ListModifier s)’
Compilation failed.
Initially I though it couldn't compose the rank 2 types but:
λ> :t (undefined :: forall a . a -> String ) . (undefined :: forall b . String -> b)
(undefined :: forall a . a -> String ) . (undefined :: forall b . String -> b)
:: String -> String
I feel the Poly module is in some way inherently inconsistent but I can't put my finger on the problem.
ListModifier is a type alias, not a “real” type. Type aliases are essentially macros at the type level, always expanded by the typechecker before actually typechecking. That means your instance declaration is equivalent to the following:
instance Monoid (forall a. s -> [a] -> [a]) where
Even if that were allowed, it would overlap with the existing Monoid (a -> b) instance, so it still wouldn’t work. The larger problem, however, is that you can’t have an instance defined on a forall-quantified type because it wouldn’t make sense from the perspective of instance resolution.
What you could do instead is define a fresh type instead of a type alias using newtype:
newtype ListModifier s = ListModifier (forall a. s -> [a] -> [a])
Now you can define a Monoid instance, since typeclass resolution only needs to look for the ListModifier type, which is much simpler to match on:
instance Monoid (ListModifier s) where
mempty = ListModifier (const id)
mappend (ListModifier f) (ListModifier g) = ListModifier (\st -> f st . g st)
Alternatively, you could keep your type alias and define a newtype with a different name, like ReifiedListModifier, then define an instance on that, and you could only do the wrapping when you need to store a ListModifier in a container or use a typeclass instance.

ScopedTypeVariables between a type class and its instance

The Haskell wiki on ScopedTypeVariables does not describe how the scope of a type variable is handled between a type class and its instance.
The following compiles
{-# LANGUAGE ScopedTypeVariables #-}
class A a where
f :: forall b. a -> b -> (a,b)
instance A Int where
f a b = (idb a, ida b)
where idb :: b -> b
idb = id
ida :: a -> a
ida = id
while the following does not (as expected: Couldn't match expected type ‘a’ with actual type ‘b’)
g :: forall a b. a -> b -> (a,b)
g a b = (idb a, b)
where idb :: b -> b
idb = id
Since the wiki is silent, how was ScopedTypeVariables supposed to work with type classes? Is this a bug, a misfeature, or by design? The wiki mentions some work-arounds that are Haskell98 and they seem to be compatible with using type classes (and thus superior).
EDIT:
As mentioned in a comment, InstanceSigs makes it possible to re-introduce the signature from the class and thus bring the type variables into scope. But this seems very awkward compared to the Haskell98 alternative:
data D
instance A D where
f a b = (idb a, b)
where idb x = asTypeOf b x -- gives the correct error message
{-# LANGUAGE InstanceSigs #-}
data E
instance A E where
-- Complicated way to bring the class signature into scope..?
f :: forall b. E -> b -> (E, b)
f a b = (idb a, b)
where idb :: b -> b
idb = id
Doesn't it make more sense that the scope from the class declaration is re-used in the instance declaration to make ScopedTypeVariables work nicely with type classes?
In the instance definition you're not using scoped type variables. There you just provide annotations for idb and ida in the where block, and both are generalized to the same type, namely forall a. a -> a (modulo renaming of type variables), so they both work on any type.
Also, in the instance definition you have A Int, so there isn't any variable you could refer to.
Generally, type variables in an instance head are visible by default in the instance implementation if we have ScopedTypeVariables, and otherwise not visible. Also, note that when visible they can be shadowed by other scoped type variables (like any other scoped type var).
Examples:
class A a where
f :: a -> b -> (a,b)
instance A a where
f x y = (x :: a, y) -- an error without ScopedTypeVariables, fine with it.
instance A a where
f x y = (x , y) where
foo :: forall a. a -> a
foo _ = x -- an error, because we shadowed the instance "a" with the forall "a"

The type variable ‘a0’ is ambiguous

I don't understand why the following code won't compile:
{-# LANGUAGE GADTs, ScopedTypeVariables #-}
data A = A
class C a where
c :: a -> Bool
instance C A where
c _ = True
data D a where
D :: C a => D a
toBool :: D a -> Bool
toBool D = c (undefined::a)
Here is the error message:
Could not deduce (C a0) arising from a use of ‘c’
from the context (C a)
bound by a pattern with constructor
D :: forall a. C a => D a,
in an equation for ‘toBool’
at test.hs:15:8
The type variable ‘a0’ is ambiguous
Note: there is a potential instance available:
instance C A -- Defined at test.hs:8:10
In the expression: c (undefined :: a)
In an equation for ‘toBool’: toBool D = c (undefined :: a)
Can someone explain what's going on ?
                                       
The type variables introduced in a top-level type declaration are not the same as those introduced inside the body of the function. Another way of saying this is the nested type declarations introduce "fresh" variables. Another another way to say this is to put explicit foralls in your code where Haskell automatically introduces them, silently:
toBool :: forall a . D a -> Bool
toBool D = c (undefined :: forall a . a) -- another forall here?
What you really intended was
toBool :: forall a . D a -> Bool
toBool D = c (undefined :: a) -- capture `a` from prior scope
and, you're in luck. It turns out that almost everyone needs this kind of functionality from time to time so a very common Haskell extension exists called ScopedTypeVariables. The following code ought to compile
{-# LANGUAGE ScopedTypeVariables #-}
toBool :: forall a . D a -> Bool
toBool D = c (undefined :: a)
Note that in order to invoke ScopedTypeVariables you must now manually introduce the foralls that you want to be treated specially. Without that manual forall Haskell will automatically introduce them at all the same locations it normally does.

more rmonad libraries?

I want to do some rudimentary things with RMonad. Are there ways of using the "as monad" functionality to
have an identity rmonad, to apply monad transformers to?
have common things like StateT transformers?
add a constraint to an existing monad? (e.g. if one wanted a StateT with additional constraints)
unfortunately I haven't yet grasped things like data families, etc. that make it work ... otherwise I'd probably be happy to write the code myself.
edit
I hacked StateT together from library sources, will see if it works ...
[ http://pastebin.com/VT3uyEgr ]
Your version of StateT looks correct after a quick glance. Unfortunately, using RMonad et. al. does require duplicating just about everything; I started doing writing some code using Suitable and gave up because it involved too much duplication (and in the end I didn't really need it).
Edit:
From my memory of how Suitable works, it's something like this:
Consider the Functor class: Set can't be an instance of it because it needs the extra Ord constraint.
A naive approach would be something like:
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
import qualified Data.Set as S
class MyFunctor c a | c -> a where
myfmap :: (MyFunctor c b) => (a -> b) -> c a -> c b
instance (Ord a) => MyFunctor S.Set a where
myfmap = S.map
But this then returns the following error:
Error: test.hs:11:16: Could not deduce (Ord b) arising from a use of `S.map'
from the context (Ord a)
bound by the instance declaration at /tmp/test.hs:10:10-37
or from (MyFunctor S.Set b)
bound by the type signature for
myfmap :: MyFunctor S.Set b => (a -> b) -> S.Set a -> S.Set b
at /tmp/test.hs:11:7-20
Possible fix:
add (Ord b) to the context of
the type signature for
myfmap :: MyFunctor S.Set b => (a -> b) -> S.Set a -> S.Set b
or the instance declaration
In the expression: S.map
In an equation for `myfmap': myfmap = S.map
In the instance declaration for `MyFunctor S.Set a'
Why is this? It's because the constraint isn't kept or found at the instance level, so GHC doesn't realise that when using myfmap, there should be an Ord constraint on b.
The Suitable type is used to explicitly create a constraint dictionary which allows you to specify these kinds of constraints:
import Data.Suitable
import qualified Data.Set as S
class MyFunctor c where
myfmap :: (Suitable c a, Suitable c b) => (a -> b) -> c a -> c b
instance MyFunctor S.Set where
myfmap f s = withConstraintsOf s
$ \ SetConstraints
-> withResConstraints $ \ SetConstraints -> S.map f s
(where SetConstraints is already defined in Data.Suitable)
This implementation works, but it does make type signatures a bit more convoluted, and method implementations a bit hairier (note here that we need to bring in SetConstraints twice: once for the Set a, the other for the Set b). Note that for types without any constraints, none of the Suitable constraint functions are needed.
I had started to try and create Suitable versions of the classes in the Typeclassopedia but gave up because the instances were getting rather hairy.

Resources