I'm new to Haskell, so I'm probably missing something obvious, but what seems to be the problem here?
The singletons library provides a Sing instance for the kind * in import Data.Singletons.TypeRepStar.
The Sing data family is defined as follows..
data family Sing (a :: k)
and the * instance is defined as..
data instance Sing (a :: *) where
STypeRep :: Typeable a => Sing a
I'm trying to reproduce a minimal version of this using the following ...
{-# LANGUAGE GADTs
, TypeFamilies
, PolyKinds
#-}
module Main where
import Data.Typeable
data family Bloop (a :: k)
data instance Bloop (a :: *) where
Blop :: Typeable a => Bloop a
main :: IO ()
main = putStrLn "Hello, Haskell!"
But I'm getting the following error...
Main.hs:12:3: error:
• Data constructor ‘Blop’ returns type ‘Bloop a’
instead of an instance of its parent type ‘Bloop a’
• In the definition of data constructor ‘Blop’
In the data instance declaration for ‘Bloop’
|
12 | Blop :: Typeable a => Bloop a
| ^
The compiler insists that the a in Bloop (a :: *) and the a in Typeable a => Bloop a are not the same a. It produces exactly the same error if you replace one of them with b:
data instance Bloop (b :: *) where
Blop :: Typeable a => Bloop a
* Data constructor `Blop' returns type `Bloop a'
instead of an instance of its parent type `Bloop b'
* In the definition of data constructor `Blop'
In the data instance declaration for `Bloop'
This can be made more visible with -fprint-explicit-kinds:
* Data constructor `Blop' returns type `Bloop k a'
instead of an instance of its parent type `Bloop * a'
* In the definition of data constructor `Blop'
In the data instance declaration for `Bloop'
Now we can clearly see right in the error message that one a has kind k and the other has kind *. From this, a solution is obvious - explicitly declare the kind of the second a :
data instance Bloop (a :: *) where
Blop :: Typeable (a :: *) => Bloop (a :: *) -- Works now
It appears that this happens because of the PolyKinds extension. Without it, the second a is assumed to have kind *, and thus the original definition works.
It appears as though the PolyKinds extension is causing the error. The singletons library splits the data family declaration and the data instance definitions into different files. The data family requires the PolyKinds extension to work, but if the instance will fail if the extension is on. It seems you must use the KindSignatures extension instead.
Def.hs
{-# LANGUAGE PolyKinds, TypeFamilies #-}
module Def (Bloop) where
data family Bloop (a :: k)
Main.hs
{-# LANGUAGE GADTs
, TypeFamilies
, KindSignatures
#-}
module Main where
import Def
import Data.Typeable
data instance Bloop (a :: *) where
Blop :: Typeable a => Bloop a
main :: IO ()
main = putStrLn "Hello, Haskell!"
Related
What is the most direct way to bind a type variable when pattern matching in a Gadt ?
#!/usr/bin/env stack
-- stack script --resolver lts-13.1
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE GADTs, ScopedTypeVariables #-}
{-# LANGUAGE DataKinds #-}
module Main where
import Data.Proxy
import GHC.TypeLits
main :: IO ()
main = undefined
data Kind where
Index :: Symbol -> Kind
data Gadt (f::Kind) where
Lit :: KnownSymbol s => Gadt ('Index s)
Binding s directly would fail
format :: Gadt f -> String
format (Lit :: Gadt ('Index s)) = undefined -- KO
with error
• Couldn't match type ‘f’ with ‘'Index s’
‘f’ is a rigid type variable bound by
the type signature for:
format :: forall (f :: Kind). Gadt f -> String
Expected type: Gadt f
Actual type: Gadt ('Index s)
A type function can extract the type, but aren't there more direct way to do this ?
format (Lit :: Gadt i) = symbolVal (Proxy :: TLabel i)
type family TLabel (a::Kind)
type instance TLabel ('Index s ) = Proxy s
The only way I see is to add a Proxy to bind the type variable with ScopedTypeVariables.
data Gadt a where
Lit :: KnownNat s => Proxy s -> Gadt ('Index s)
format :: Gadt a -> String
format (Lit (Proxy :: Proxy s)) = undefined
If you are worried about the extra allocation, the field can be unpacked. (EDIT: removed previous mention of Proxy# because that doesn't seem necessary).
import Data.Proxy
-- This should be as efficient as the original Gadt with a nullary Lit
data Gadt a where
Lit :: {-# UNPACK #-} !(Proxy r) -> Gadt ('Index r)
format :: Gadt a -> String
format (Lit (_ :: Proxy r)) = undefined
On the longer term, the following GHC proposal will address this issue: Type Applications in Patterns.
-- The original type
data Gadt a where
Lit :: forall s. Gadt ('Index s)
format :: Gadt a -> String
format (Lit #s) = ...
I have the following snippet:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeInType #-}
import Data.Proxy
data Foo where
FooInt :: Foo
FooProxy :: IsEnum e ~ True => Proxy e -> Foo
type family IsEnum e :: Bool
type family FromFoo (foo :: Foo) where
FromFoo FooInt = Int
FromFoo (FooProxy ('Proxy :: Proxy e)) = e
The general idea is that I'm trying to use Foo as a data kind where I could do
type MyFoo1 = FooInt :: Foo
type instance IsEnum Bool = True
type MyFoo2 = FooProxy ('Proxy :: Proxy Bool) :: Foo
and ensure that the proxied type being passed to FooProxy is a part of the IsEnum type family (I can't just do FooProxy :: Enum e => Proxy e -> Foo because only equality constraints are currently supported).
But when I try to compile this, I get the error:
<interactive>:30:12: error:
• Couldn't match expected kind ‘'True’ with actual kind ‘IsEnum e’
• In the first argument of ‘FromFoo’, namely
‘(FooProxy ( 'Proxy :: Proxy e))’
In the type family declaration for ‘FromFoo’
The problem is when I want to convert from my Foo type to the concrete type in FromFoo, I want FooProxy to evaluate to the proxied type. So I'm trying to pattern match on Proxy to return the proxied type e, but then it seems to be checking the IsEnum e ~ True constraint again. I would think that the constraint would only be checked when creating a FooProxy value, but it seems to be checking again when pattern matching.
I'm trying to derive a Typeable instance for tupled constraints. See the following code:
{-# LANGUAGE ConstraintKinds, GADTs #-}
{-# LANGUAGE DataKinds, PolyKinds, AutoDeriveTypeable #-}
{-# LANGUAGE StandaloneDeriving, DeriveDataTypeable #-}
import Data.Proxy
import Data.Typeable
data Foo (p :: (*, *))
data Dict ctx where
Dict :: ctx => Dict ctx
deriving (Typeable)
deriving instance Typeable '(,)
deriving instance Typeable Typeable
deriving instance Typeable Show
works :: IO ()
works = print (typeRep (Proxy :: Proxy (Foo '(Bool, Char))))
alsoWorks :: IO ()
alsoWorks = print (typeRep (Dict :: Dict (Show Bool)))
fails :: IO ()
fails = print (typeRep (Dict :: Dict (Show Bool, Typeable Bool)))
main :: IO ()
main = works >> alsoWorks >> fails
If you compile this with -fprint-explicit-kinds, the following error is given:
No instance for (Typeable
(Constraint -> Constraint -> Constraint) (,))
Is there a way to derive such an instance? Everything I try refuses to disambiguate from the ★ -> ★ -> ★ constructor.
GHC can not currently make a Typeable instance, or any other instance, for (,) :: Constraint -> Constraint -> Constraint. The type constructor (,) only has kind * -> * -> *. There is no type constructor for products of the kind Constraint -> Constraint -> Constraint. The constructor (,) is overloaded to construct both tuples and products of Constraints, but has no corresponding type constructor when used to make a product of Constraints.
If we did have a type constructor for products of Constraints we should be able to define an instance as follows. For this, we'll pretend (,) is also a type constructor with kind (,) :: Constraint -> Constraint -> Constraint. To define an instance for it, we'd use KindSignatures and import GHC.Exts.Constraint to be able to talk about the kind of constraints explicitly
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE KindSignatures #-}
import GHC.Exts (Constraint)
import Data.Typeable
deriving instance Typeable ((,) :: Constraint -> Constraint -> Constraint)
If we do this now, it results in the following error, due to the kind of the (,) type constructor.
The signature specified kind `Constraint
-> Constraint -> Constraint',
but `(,)' has kind `* -> * -> *'
In the stand-alone deriving instance for
`Typeable ((,) :: Constraint -> Constraint -> Constraint)'
The constraints package also works with products of constraints, and includes the following note.
due to the hack for the kind of (,) in the current version of GHC we can't actually make instances for (,) :: Constraint -> Constraint -> Constraint
I presume the hack Edward Kmett is referring to is the overloading of the (,) constructor for Constraints without a corresponding type constructor.
It seems that it is not currently possible. There's a revealing comment in the latest version of constraint:
due to the hack for the kind of (,) in the current version of GHC we can't actually make instances for (,) :: Constraint -> Constraint -> Constraint
I'm trying to do a 'UnMaybe' type family but it doesn't compile (instance family conflicting).
Here is my code
{-# LANGUAGE TypeFamilies #-}
type family UnMaybe a :: *
type instance UnMaybe (Maybe a) = a
type instance UnMaybe a = a
Error message
test.hs:4:16:
Conflicting family instance declarations:
type instance UnMaybe (Maybe a)
-- Defined at test.hs:4:16
type instance UnMaybe a
-- Defined at test.hs:5:15
I understand why it's not working, anyway is there another way to achieve the same result (or an extension to activate which will allow it?)
If you really need this, you can use a closed type family (requires at least GHC 7.8):
{-# LANGUAGE TypeFamilies #-}
type family UnMaybe a :: * where
UnMaybe (Maybe a) = a
UnMaybe a = a
Now:
GHCi> :kind! UnMaybe (Maybe Int)
UnMaybe (Maybe Int) :: *
= Int
GHCi> :kind! UnMaybe Bool
UnMaybe Bool :: *
= Bool
I've been slowly working on porting the llvm package to use data kinds, type families and type-nats and ran into a minor issue when trying to remove the two newtypes used for classifying values (ConstValue and Value) by introducing a new Value type parameterized by its constness.
CallArgs only accepts Value 'Variable a arguments and provides a function for casting a Value 'Const a to a Value 'Variable a. I'd like to generalize CallArgs to allow each argument to be either 'Const or 'Variable. Is this possible to encode this somehow using type families? I think it's probably doable with fundeps.
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
data Const = Const | Variable
data Value (c :: Const) (a :: *)
type family CallArgs a :: *
type instance CallArgs (a -> b) = forall (c :: Const) . Value c a -> CallArgs b
type instance CallArgs (IO a) = IO (Value 'Variable a)
... which fails to compile:
/tmp/blah.hs:10:1:
Illegal polymorphic or qualified type:
forall (c :: Const). Value c a
In the type instance declaration for `CallArgs'
Where the following solution works (equivalent to the legacy code), but requires the user to cast the each constant Value:
type family CallArgs' a :: *
type instance CallArgs' (a -> b) = Value 'Variable a -> CallArgs' b
type instance CallArgs' (IO a) = IO (Value 'Variable a)
The CallArgs you're asking for is kind of like a non-deterministic function which takes a -> b and returns either Value 'Const a -> blah or Value 'Variable a -> blah. One thing you can sometimes to with nondeterministic functions is flip them around; indeed, this one has a deterministic inverse.
type family UnCallArgs a
type instance UnCallArgs (Value c a -> b) = a -> UnCallArgs b
type instance UnCallArgs (IO 'Variable a) = IO a
Now, anywhere you would have written a type like
foo :: CallArgs t -> LLVM t
or something like that, you can write this instead:
foo :: t -> LLVM (UnCallArgs t)
Of course, you might want to pick a better name than UnCallArgs, maybe Native or something like that, but doing that well requires a bit of domain knowledge that I don't have.
Would wrapping the forall c. in a newtype AV work for you?
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
data CV = Const | Variable
data Value (c :: CV) (a :: *)
data AV a = AV (forall c. Value c a)
type family CallArgs a :: *
type instance CallArgs (a -> b) = AV a -> CallArgs b
type instance CallArgs (IO a) = IO (Value 'Variable a)