采取以下代码:
{-# LANGUAGE KindSignatures, DataKinds #-}
data Nat = O | S Nat
class NatToInt (n :: Nat) where
natToInt :: n -> Int
instance NatToInt O where
natToInt _ = 0
instance (NatToInt n) => NatToInt (S n) where
natToInt _ = 1 + natToInt (undefined :: n)
GHC 告诉我们它OpenKind
在类型规范中期望natToInt
a 而不是 a Nat
,因此拒绝编译。这可以通过某种类型的转换来解决:
data NatToOpen :: Nat -> *
然后用n
in NatToOpen n
t替换natToInt
-s。
*
问题 1:除了在任何函数中不使用类型级包装器之外,还有其他方法可以指定种类吗?
问题 2:在我看来,非类函数很乐意与任何类型的类型一起工作,例如:
foo :: (a :: *) -> (a :: *)
foo = id
bar = foo (S O)
但是在类内部,编译器会抱怨种类不匹配,如上所述。这是为什么?似乎非类函数在种类上不是适当的多态,因为上面我实际上指定 *
了 ,它仍然可以与Nat
-s 一起使用,就好像这些种类被简单地忽略了一样。