在其构造函数之一中创建 Haskell 接受非 * 类型的数据类型
Creating Haskell datatype accepting type of non-* kind in one of its constructors
您好。我正在玩 Ivory 库,它严重依赖 Haskell 的现代特性。其中,它定义了 typeclasses IvoryType
接受所有类型和 IvoryArea
接受特殊类型 Area
的类型。定义如下所示:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ExistentialQuantification #-}
-- | Proxy datatype with a phantom arbitrary-kinded type
-- and a single constructor
data Proxy (a :: k) = Proxy
-- | The kind of memory-area types.
data Area k
= Struct Symbol
| Array Nat (Area k)
| CArray (Area k)
| Stored k
-- ^ This is lifting for a *-kinded type
class IvoryType t where
ivoryType :: Proxy t -> I.Type {- arguments are not important -}
-- | Guard the inhabitants of the Area type, as not all *s are Ivory *s.
class IvoryArea (a :: Area *) where
ivoryArea :: Proxy a -> I.Type {- arguments are not important -}
好的。现在让我们尝试表达一个事实,即我们将使用定义的 ivoryType
函数存储值。显然,他们是IvoryType
class的成员,所以答案是
data TypeStorage = TypeStorage (forall t . IvoryType t => t)
到目前为止一切顺利。现在我们要存储定义了 ivoryArea
函数的值。让我们使用 IvoryArea
class 作为过滤条件,就像前面的情况一样:
data AreaStorage = AreaStorage (forall t . IvoryArea t => t)
令人惊讶的是,编译器(ghc 版本 7.8.4)输出错误
src/IvoryLL/Types.hs:59:45:
Expected a type, but ‘t’ has kind ‘Area *’
In the type ‘forall t. IvoryArea t => t’
In the definition of data constructor ‘AreaBase’
In the data declaration for ‘Area
能否请您解释一下,如何在 Haskell 中正确表达 ivoryArea
函数的所有权?
编辑
原始声明的一些链接:
既然我们已经在评论中确定你不能直接做你想做的事情,那就是创建一个特殊的 "subkind" 所有类型,我们 可以 多花点功夫来得到你想要的。
我们只是使用(封闭的)类型族将您的 Area *
种类解释为 *
种类,然后使用 Area *
索引的 GADT 来保存这些值。然后,如果需要,我们可以将整个 shebang 包装在一个 existential 中以存储此类任意值。
考虑这个缩减示例:
data Area k
= Stored k
| List (Area k)
type family InterpIvoryArea a :: * where
InterpIvoryArea (Stored k) = k
InterpIvoryArea (List a) = [InterpIvoryArea a]
data AreaStorage a where
AreaStorage :: InterpIvoryArea a -> AreaStorage a
data AreaStorageExistential where
AreaStorageExistential :: AreaStorage a -> AreaStorageExistential
testValue :: AreaStorageExistential
testValue = AreaStorageExistential (AreaStorage [1,2,3] :: AreaStorage (List (Stored Int)))
您好。我正在玩 Ivory 库,它严重依赖 Haskell 的现代特性。其中,它定义了 typeclasses IvoryType
接受所有类型和 IvoryArea
接受特殊类型 Area
的类型。定义如下所示:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ExistentialQuantification #-}
-- | Proxy datatype with a phantom arbitrary-kinded type
-- and a single constructor
data Proxy (a :: k) = Proxy
-- | The kind of memory-area types.
data Area k
= Struct Symbol
| Array Nat (Area k)
| CArray (Area k)
| Stored k
-- ^ This is lifting for a *-kinded type
class IvoryType t where
ivoryType :: Proxy t -> I.Type {- arguments are not important -}
-- | Guard the inhabitants of the Area type, as not all *s are Ivory *s.
class IvoryArea (a :: Area *) where
ivoryArea :: Proxy a -> I.Type {- arguments are not important -}
好的。现在让我们尝试表达一个事实,即我们将使用定义的 ivoryType
函数存储值。显然,他们是IvoryType
class的成员,所以答案是
data TypeStorage = TypeStorage (forall t . IvoryType t => t)
到目前为止一切顺利。现在我们要存储定义了 ivoryArea
函数的值。让我们使用 IvoryArea
class 作为过滤条件,就像前面的情况一样:
data AreaStorage = AreaStorage (forall t . IvoryArea t => t)
令人惊讶的是,编译器(ghc 版本 7.8.4)输出错误
src/IvoryLL/Types.hs:59:45:
Expected a type, but ‘t’ has kind ‘Area *’
In the type ‘forall t. IvoryArea t => t’
In the definition of data constructor ‘AreaBase’
In the data declaration for ‘Area
能否请您解释一下,如何在 Haskell 中正确表达 ivoryArea
函数的所有权?
编辑 原始声明的一些链接:
既然我们已经在评论中确定你不能直接做你想做的事情,那就是创建一个特殊的 "subkind" 所有类型,我们 可以 多花点功夫来得到你想要的。
我们只是使用(封闭的)类型族将您的 Area *
种类解释为 *
种类,然后使用 Area *
索引的 GADT 来保存这些值。然后,如果需要,我们可以将整个 shebang 包装在一个 existential 中以存储此类任意值。
考虑这个缩减示例:
data Area k
= Stored k
| List (Area k)
type family InterpIvoryArea a :: * where
InterpIvoryArea (Stored k) = k
InterpIvoryArea (List a) = [InterpIvoryArea a]
data AreaStorage a where
AreaStorage :: InterpIvoryArea a -> AreaStorage a
data AreaStorageExistential where
AreaStorageExistential :: AreaStorage a -> AreaStorageExistential
testValue :: AreaStorageExistential
testValue = AreaStorageExistential (AreaStorage [1,2,3] :: AreaStorage (List (Stored Int)))