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.
Related
Why is GHC inferring unification from coercibility of associated data, and why is it contradicting its own checked type signature to do so?
The problem
{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeFamilies #-}
module Lib
(
) where
import Data.Coerce
class Foo a where
data Bar a
data Baz a = Baz
{ foo :: a
, bar :: Bar a
}
type BarSame a b = (Coercible (Bar a) (Bar b), Coercible (Bar b) (Bar a))
withBaz :: forall a b. BarSame a b => (a -> b) -> Baz a -> Baz b
withBaz f Baz{..} = Baz
{ foo = f foo
, bar = coerce bar
}
This is all well and good - GHC will happily compile this code, and is confident that withBaz has the declared signature.
Now, let's try to use it!
instance (Foo a) => Foo (Maybe a) where
data Bar (Maybe a) = MabyeBar (Bar a)
toMaybeBaz :: Baz a -> Baz (Maybe a)
toMaybeBaz = withBaz Just
This gives an error - but a really weird one:
withBaz Just
^^^^^^^^^^^^
cannot construct the infinite type: a ~ Maybe a
Indeed, if I go into GHCi, and ask it to give me the type of withBaz:
ghc>:t withBaz
withBaz :: (b -> b) -> Baz b -> Baz b
That's not the signature I gave it.
Coercibility
I suspect that GHC is treating the type arguments of withBaz as though they have to unify, because it's inferring Coercible a b from Coercible (Bar a) (Bar b). But because it's a data family, they don't even need to be Coercible - certainly not unifiable.
Update!
The following change fixes the compilation:
instance (Foo a) => Foo (Maybe a) where
newtype Bar (Maybe a) = MabyeBar (Bar a)
That is - declare the data family as a newtype, instead of a data. This seems consistent with GHC's treatment of Coercible in the language in general, in that
data Id a = Id a
will not cause a Coercible instance to be generated - even though it should definitely be coercible to a. With the above declaration, this will error:
wrapId :: a -> Id a
wrapId = coerce
But with a newtype declaration:
newtype Id a = Id a
then the Coercible instance exists, and wrapId compiles.
I believe #dfeuer's since-deleted comment about lack of "role" support for type/data families provides the answer.
For a top-level, data-defined parametrized type:
data Foo a = ...
the coercibility of types Foo a and Foo b depends on the role of the parameter a. In particular, if as role is nominal, then Foo a and Foo b are coercible if and only if a and b are precisely the same type.
So, in the program:
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RoleAnnotations #-}
import Data.Coerce
type role Foo nominal
data Foo a = Foo
foo :: (Coercible (Foo a) (Foo b)) => a -> b
foo = undefined
because of the nominal role of the parameter a in Foo a, the type of foo is actually simplified to b -> b:
λ> :t foo
foo :: b -> b
If the role annotation is changed from nominal to representational, the type is simplified to Coercible a b => a -> b, and if the role is changed to phantom (the default for this particular declaration of Foo, as a does not appear on the right-hand side), the type is simplified to a -> b. This is all as expected and corresponds to the definition of each of these roles.
Note that if you replaced the declaration of Foo with:
data Foo a = Foo a
then the phantom role would not longer be permitted, but the inferred types for foo under the other two roles would be exactly as before.
However, there's an important difference if you switch from a data to a newtype. With:
newtype Foo a = Foo a
you'd discover that even with type role Foo nominal, the inferred type for foo would be Coercible b a => a -> b instead of b -> b. That's because the algorithm for type-safe coercions handles newtypes differently than "equivalent" data types, as you've noted in your question -- they are always immediately coercible through unwrapping whenever the constructor is in scope, regardless of the role of the type parameter.
So, with all that being said, your experience with associated data families is consistent with the role of the family's type parameter being set to nominal. Though I couldn't find it documented in the GHC manual, this appears to be as-designed behavior, and there's an open ticket that acknowledges all data/type families have all parameters assigned nominal role and proposes relaxing this restriction, and #dfeuer actually has a detailed proposal from this past October.
Why doesn't using an associated type synonym in a signature imply the corresponding constraint?
E.g. why doesn't the following compile:
{-# LANGUAGE TypeApplications, ScopedTypeVariables, TypeFamilies, AllowAmbiguousTypes #-}
class MyClass a where
type AssociatedType a
bar :: Int
foo :: forall a. AssociatedType a -> Int
foo _ = bar #a
ghc 8.6.5 gives the following error:
error:
* No instance for (MyClass a) arising from a use of `bar'
Possible fix:
add (MyClass a) to the context of
the type signature for:
foo :: forall a. AssociatedType a -> Int
* In the expression: bar #a
In an equation for `foo': foo _ = bar #a
|
8 | foo _ = bar #a
| ^^^^^^
GHC documentation doesn't seem to mention this aspect.
If it implied the constraint, then anybody using values of the associated value in any way whatsoever would need to have the constraint in scope. For example,
sort :: Ord a => [a] -> [a]
obviously knows nothing about MyClass, yet it should be possible to use it as sort :: [AssociatedType a] -> [AssociatedType a] provided that you have Ord (AssociatedType a) in the calling scope.
To get behaviour like the one you seem to be looking for, you want a wrapped constraint rather than an associated type. That can't be done with -XTypeFamilies, but it can be done with -XGADTs:
{-# LANGUAGE GADTs #-}
class MyClass a where
bar :: Int
data MyClassWitness a where
MyClassWitness :: MyClass a => MyClassWitness a
foo :: ∀ a. MyClassWitness a -> Int
foo MyClassWitness = bar #a
Instead of a self-rolled wrapper you can also use the one from the constraints library:
import Data.Constraint
foo :: ∀ a . Dict (MyClass a) -> Int
foo Dict = bar #a
Important in both cases is that you actually pattern-match on the GADT constructor, as only that actually brings the constraint into scope. This would not work:
foo :: ∀ a . Dict (MyClass a) -> Int
foo _ = bar #a
Because just using the type does not require the type constraint. For instance, this compiles:
foo :: forall a. AssociatedType a -> Int
foo _ = 42
At runtime, there is no need to pass a typeclass dictionary to this function, which is coherent with the lack of the constraint during type checking.
In your code, the constraint is needed because you are using bar, not because you are using the type.
Is there a Haskell language extension for the type class method to "use the only potential instance available"?
I want to compile the following
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
class Foo a r where
foo :: a -> r
instance Foo a (Bool -> a) where
foo x _ = x
-- This compiles
-- bar :: Int -> Bool
-- This does not
bar :: a -> Bool
bar _ = True
use :: Bool
use = bar $ foo _5 True
where
_5 :: Int
_5 = 5
Now I get the following error:
No instance for (Foo Int (Bool -> r0))
(maybe you haven't applied enough arguments to a function?)
arising from a use of ‘foo’
The type variable ‘r0’ is ambiguous
Note: there is a potential instance available:
instance Foo a (Bool -> a) -- Defined at tests/pos/Fixme.hs:9:10
But since there is only one potential instance available, is there a way to force ghc to use that instance? Or is there a way to declare some instance as a default instance when types are ambiguous?
The standard trick is to make your instance more polymorphic, thus:
instance (a ~ b, bool ~ Bool) => Foo a (bool -> b) where
foo x _ = x
This precludes you from writing other function instances, but makes it clear what types to use when a function instance is wanted. You will need to turn on the TypeFamilies extension to do this. In your specific case you may be able to get away with just instance a ~ b => Foo a (Bool -> b), which would allow further function instances with other argument types, at the cost of more frequent ambiguity errors.
See a previous answer of mine for some more explanation of this trick.
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.)
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.