这是我正在尝试编写的一个简化的,也许是愚蠢的例子(更复杂,涉及列表长度的编译时编码)。
鉴于以下内容:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE GADTs #-}
data D (a :: Bool) where
D :: Bool -> D a
我想要以下函数g
:
g :: D a -> Bool
g (D x) = x == a
当然这不会编译,因为a
是一个类型,而不是一个值。
这是一个可能的解决方案:
class C (a :: Bool) where
f :: D a -> Bool
instance C True where
f (D x) = x == True
instance C False where
f (D x) = x == False
g :: (C a) => D a -> Bool
g = f
但是我必须向g
添加约束,这似乎是a :: Bool
的冗余,并且我已经为Bool
的所有情况提供了实例。
无论如何,我可以写g
使其具有签名:
g :: D a -> Bool
即。不需要额外的约束?
答案 0 :(得分:7)
不,这是不可能的,因为我可以为您提供D Any
类型的完美价值,其中Any
已定义
type family Any :: k where {}
你能做的就是写一个更普遍有用的课程:
data SBool a where
SFalse :: SBool 'False
STrue :: SBool 'True
sBoolToBool :: SBool a -> Bool
sBoolToBool SFalse = False
sBoolToBool STrue = True
class KnownBool a where
knownBool :: SBool a
instance KnownBool 'False where
knownBool = SFalse
instance KnownBool 'True where
knownBool = STrue
当然,如果你没有将这些类型用于其他任何事情,那么所有这些机器都是过度的。