Why is GHC contradicting itself when using a Coercible constraint? - haskell

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.

Related

Why doesn't associated type synonym imply the constraint

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.

Returning a subset of types in Haskell

I'm trying to restrict the return type of a function to a subset of (kind) constructors. I can use typeclasses to restrict the input types, but when I try the same technique on return types as shown below, I get a Couldn't match type ‘s’ with ‘'A’ error.
Is there a way to restrict the bar function below to return either SomeA or SomeB?
It seems that Liquid Haskell is an alternative, but it seems that this should be possible using only things like DataKinds, GADTs and/or TypeInType.
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
module Test where
data State = A | B | C
class AorB (s :: State)
instance AorB 'A
instance AorB 'B
data Some (s :: State) where
SomeA :: Some 'A
SomeB :: Some 'B
SomeC :: Some 'C
-- This works
foo :: AorB s => Some s -> Bool
foo aorb = case aorb of
SomeA -> True
SomeB -> False
-- This fails to compile with ""Couldn't match type ‘s’ with ‘'A’""
bar :: AorB s => Some s
bar = SomeA
A few things here. If you compile with -Wall (which you should!) you would find that your definition of foo gives an inexhaustive patterns warning. And it should, because the way you have defined AorB is "open". That is, somebody in another module is free to declare
instance AorB 'C
and then your definition of foo will suddenly become invalid as it fails to handle the SomeC case. To get what you are looking for, you should use a closed type family:
type family IsAorB s where
IsAorB 'A = 'True
IsAorB 'B = 'True
IsAorB _ = 'False
This family is totally defined on States. We would then define your previous AorB constraint like so:
type AorB s = IsAorB s ~ 'True
However, in a moment we will need to use AorB in curried form, which is not allowed for type synonyms. There is an idiom for declaring curriable synonyms which is a bit clunky, but is the best we have at the moment:
class (IsAorB s ~ 'True) => AorB s
instance (IsAorB s ~ 'True) => AorB s
Anyway, with this new definition, you will find that the inexhaustive pattern warning goes away for foo. Good.
Now on to your question. The trouble with your definition (with an explicit forall added for clarity)
bar :: forall s. AorB s => Some s
bar = SomeA
is that we are allowed to instantiate bar #B, giving us
bar #B :: AorB B => Some B
bar = SomeA
AorB B is satisfiable, so we should be able to get a Some B, right? But not according to your implementation. So something is logically wrong here. You are probably looking to return an existentially quantified s, in other words, you want the bar function to choose which s it is, not the caller. Informally
bar :: exists s. AorB s <AND> Some s
That is, bar chooses an s, and returns a Some s, together with some evidence that AorB s holds. This is no longer an implication, we would not put the responsibility on the caller to prove that the type bar chose was either A or B -- the caller has no idea what was chosen.
Haskell does not directly support existential types, but we can model them with a GADT (make sure to use PolyKinds and ConstraintKinds)
data Ex c f where
Ex :: c a => f a -> Ex c f
Ex c f can be read as "there exists a such that c a holds and there is a value f a". This is existential becuase the variable a does not appear in Ex c f, it's hidden by the constructor. And now we can implement bar
bar :: Ex AorB Some
bar = Ex SomeA
We can test that the constraints are correctly propagated by passing this to your foo:
test :: Bool
test = case bar of Ex s -> foo s
There you go.
That said, design-wise I would just say
bar :: Some A
instead. Type signatures should be as informative as possible. Don't hide information that you know -- let abstraction do the hiding. When you hide information about your assumptions/arguments, you are making your signature stronger; when you hide about your results, you are making it weaker. Make it strong.
Here is the full working code based on #luqui's answer, for reference:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleInstances #-}
module Test2 where
data State = A | B | C
type family IsAorB (s :: State) where
IsAorB 'A = 'True
IsAorB 'B = 'True
IsAorB _ = 'False
-- type AorB s = IsAorB s ~ 'True
class (IsAorB s ~ 'True) => AorB s
instance (IsAorB s ~ 'True) => AorB s
data Some (s :: State) where
SomeA :: Some 'A
SomeB :: Some 'B
SomeC :: Some 'C
data Ex c f where
Ex :: c a => f a -> Ex c f
bar :: Ex AorB Some
bar = Ex SomeA

Choose default instance under ambiguous types

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.

Circular Typing with Constraints

In the example below, I'm trying to make foo return its "expected" polymorphic output type. The idea is that foo returns a polymorphic value and an existential type, and then bar specifies the type of the tuple to be the hidden type. (Of course this only works if the type in bar is also existential, which is true in my case.) The following example compiles:
{-# LANGUAGE GADTs, ScopedTypeVariables #-}
module Foo where
import Data.Proxy
import Data.Typeable
data HiddenType where
Hidden :: (Typeable a) => Proxy a -> HiddenType
foo :: (i,HiddenType)
foo = (undefined, Hidden (Proxy::Proxy Int))
data Foo where
Foo :: i -> Foo
bar :: Foo
bar =
let (x,h) = foo
in case h of
(Hidden (p::Proxy i)) -> Foo (x :: i)
I really need a Typeable constraint on foo:
foo :: (Typeable i) => (i,HiddenType)
When I add that constraint (no other changes), I get these errors:
Foo.hs:20:15:
No instance for (Typeable t0) arising from a use of ‘foo’
The type variable ‘t0’ is ambiguous
Relevant bindings include x :: t0 (bound at Foo.hs:20:8)
Note: there are several potential instances:
instance [overlap ok] Typeable ()
-- Defined in ‘Data.Typeable.Internal’
instance [overlap ok] Typeable Bool
-- Defined in ‘Data.Typeable.Internal’
instance [overlap ok] Typeable Char
-- Defined in ‘Data.Typeable.Internal’
...plus 14 others
In the expression: foo
In a pattern binding: (x, h) = foo
In the expression:
let (x, h) = foo
in case h of { (Hidden (p :: Proxy i)) -> Foo (x :: i) }
Foo.hs:22:35:
Couldn't match expected type ‘a’ with actual type ‘t0’
because type variable ‘a’ would escape its scope
This (rigid, skolem) type variable is bound by
a pattern with constructor
Hidden :: forall a. Typeable a => Proxy a -> HiddenType,
in a case alternative
at Foo.hs:22:6-24
Relevant bindings include
p :: Proxy a (bound at Foo.hs:22:14)
x :: t0 (bound at Foo.hs:20:8)
In the first argument of ‘Foo’, namely ‘(x :: i)’
In the expression: Foo (x :: i)
Failed, modules loaded: none.
I understand that constraints turn into arguments in core, so it seems to me that the issue here is that GHC can't handle pattern bindings for GADTs. If it could, I could use a recursive let to say something like:
bar :: Foo
bar =
let (x :: i,h) = foo
(Hidden (p::Proxy i)) = h
in Foo x
That should make the constraint in scope, providing the extra argument to foo. My intent here is that h contains some (hidden) concrete type i, which should be used as the concrete type for the polymorphic function
GHC complains:
Foo.hs:19:8:
You cannot bind scoped type variable ‘i’
in a pattern binding signature
In the pattern: x :: i
In the pattern: (x :: i, h)
In a pattern binding:
(x :: i, h) = foo
Foo.hs:20:8:
My brain just exploded
I can't handle pattern bindings for existential or GADT data constructors.
Instead, use a case-expression, or do-notation, to unpack the constructor.
In the pattern: Hidden (p :: Proxy i)
In a pattern binding: (Hidden (p :: Proxy i)) = h
In the expression:
let
(x :: i, h) = foo
(Hidden (p :: Proxy i)) = h
in Foo x
The assumptions for my use case are that
1. foo computes i and the HiddenType simultaneously
2. The value of the hidden type involves (at least partial) computation of the first tuple element. This means I do not want to call foo twice in bar (once to get the HiddenType, and once to use that type to bind the first tuple element).
Is there some way to make the definition of bar possible in the presence of a constraint on foo?
I suppose the problem is that foos return value isn't actually polymorphic. foo itself is polymorphic but the returned value must exist at a specific type. Unfortunately, the type you want to use isn't available yet and cannot be brought into scope at foos call site because of the circular reference. If we write out the definition of foo in pseudo-core, the problem is clear:
foo (# iType) _ = (undefined # iType, HiddenType...)
Here # iType is a type argument. We need to do foo's type application first (and the dictionary application, which is unused) before getting the HiddenType, so there's no way to make this work as-is.
Fortunately, there is a way to convince ghc that foo should return an actual polymorphic value:
{-# LANGUAGE GADTs, ScopedTypeVariables #-}
{-# LANGUAGE ImpredicativeTypes #-}
module Foo where
import Data.Proxy
import Data.Typeable
data HiddenType where
Hidden :: (Typeable a) => Proxy a -> HiddenType
foo :: (forall i. Typeable i => i,HiddenType)
foo = (undefined, Hidden (Proxy::Proxy Int))
data Foo where
Foo :: i -> Foo
bar =
let (x,h) = foo
in case h of
Hidden p -> Foo (x `asProxyTypeOf` p)
If you're familiar with higher-rank types (e.g. the RankNTypes extension), you can think of ImpredicativeTypes as something similar, except for data structures instead of functions. For example, without ImpredicativeTypes you can write:
list1 :: forall t. Typeable t => [t]
which is the type of a list that contains all values of type t, for some t with a Typeable constraint. Even though it's polymorphic, every element of the list will be of the same type! If instead you wish to move the forall inside the list, so that every element may be a different type t, ImpredicativeTypes will allow this:
list2 :: [forall t. Typeable t => t]
It's not a commonly-enabled extension, but it is occasionally useful.
The core for the impredicative version of foo is a bit different as well:
foo = (\(# iType) _ -> undefined # iType, HiddenType...)
You can see that this allows for x to be polymorphic as desired if you add an annotation to the let:
bar :: Foo
bar =
let (x :: forall i. Typeable i => i,h) = foo
in case h of
Hidden p -> Foo (x `asProxyTypeOf` p)
This allows you to delay the instantiation of x at the hidden type until later, when it's available. You still need to box it up inside Foo or another Hidden though, as ghc won't allow the type to escape from under the first Hidden pattern match.

Haskell error: cannot derive well-kinded instance / kind-mismatch

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.

Resources