类 中的种类多态性
Kind-polymorphism in classes
我 recently ran into a problem using kind polymorphism with GADTs. The answer there was to give a "complete user-specified kind" (CUSK) for my data type. I've read the relevant documentation,但是当我尝试将其应用于 class 时,我仍然遇到基本相同的错误。
具体来说,一旦我给出一个 CUSK,以下 会 编译:
{-# LANGUAGE DataKinds, PolyKinds, GADTs #-}
data Foo (x :: k) where
C :: Foo x -> Foo '(x,x)
但是当我将该定义移动到 class:
{-# LANGUAGE DataKinds, PolyKinds #-}
class Foo (f :: k -> *) where
foo :: (f :: k1 -> *) (x :: k1) -> (f :: (k1,k1) -> *) ('(x,x) :: (k1,k1))
我收到错误:
• Expected kind ‘(k1, k1) -> *’, but ‘f’ has kind ‘k -> *’
• In the type signature:
foo :: (f :: k1 -> *) (x :: k1) -> (f :: (k1, k1) -> *) ('(x, x) :: (k1, k1))
In the class declaration for ‘Foo’
我希望我需要做一些小事来说服 GHC 在第二个示例中 f
是一种多态性。
这是 GHC 8 和 TypeInType
的工作,它允许更多有趣的依赖形式。以下对您的代码进行类型检查的小修改。
{-# LANGUAGE PolyKinds, RankNTypes, KindSignatures,
DataKinds, TypeInType #-}
module KP where
import Data.Kind
class Foo (f :: forall k. k -> *) where
foo :: (f :: k1 -> *) (x :: k1) -> (f :: (k1,k1) -> *) ('(x,x) :: (k1,k1))
重要的是,在 class 类型参数的(哈哈!)type 中使用 forall
不再是语法错误。
我 recently ran into a problem using kind polymorphism with GADTs. The answer there was to give a "complete user-specified kind" (CUSK) for my data type. I've read the relevant documentation,但是当我尝试将其应用于 class 时,我仍然遇到基本相同的错误。
具体来说,一旦我给出一个 CUSK,以下 会 编译:
{-# LANGUAGE DataKinds, PolyKinds, GADTs #-}
data Foo (x :: k) where
C :: Foo x -> Foo '(x,x)
但是当我将该定义移动到 class:
{-# LANGUAGE DataKinds, PolyKinds #-}
class Foo (f :: k -> *) where
foo :: (f :: k1 -> *) (x :: k1) -> (f :: (k1,k1) -> *) ('(x,x) :: (k1,k1))
我收到错误:
• Expected kind ‘(k1, k1) -> *’, but ‘f’ has kind ‘k -> *’
• In the type signature:
foo :: (f :: k1 -> *) (x :: k1) -> (f :: (k1, k1) -> *) ('(x, x) :: (k1, k1))
In the class declaration for ‘Foo’
我希望我需要做一些小事来说服 GHC 在第二个示例中 f
是一种多态性。
这是 GHC 8 和 TypeInType
的工作,它允许更多有趣的依赖形式。以下对您的代码进行类型检查的小修改。
{-# LANGUAGE PolyKinds, RankNTypes, KindSignatures,
DataKinds, TypeInType #-}
module KP where
import Data.Kind
class Foo (f :: forall k. k -> *) where
foo :: (f :: k1 -> *) (x :: k1) -> (f :: (k1,k1) -> *) ('(x,x) :: (k1,k1))
重要的是,在 class 类型参数的(哈哈!)type 中使用 forall
不再是语法错误。