考虑一下,我有类型标记:
data Uniq = Uniq deriving Show
data NUniq = NUniq deriving Show
data UUniq = UUniq deriving Show
并用谓词来区分它们:
type family IsMark a :: Bool
type instance IsMark Uniq = 'True
type instance IsMark NUniq = 'True
type instance IsMark UUniq = 'True
并将“转换器”从'[A, B, ..]
转换为A -> B -> ..
:
type Id x = x
type Fn x y = x -> y
type family TL2Fun xs where
TL2Fun '[x] = Id x
TL2Fun (x ': xs) = Fn x (TL2Fun xs)
所以这个签名是正确的:
f1 :: TL2Fun '[Int, Int, Int]
f1 a b = a + b
现在我想要这个:
f2 :: TL2Fun (WOMarks '[Int, Int, Int, Uniq])
f2 a b = a + b
即首先从此列表中滤除Uniq
。因此,我根据谓词添加了过滤器功能:
type family WOMarks xs where
WOMarks '[] = '[]
WOMarks (x ': xs) = If (IsMark x) (WOMarks xs) (x ': (WOMarks xs))
其中If
是从Data.Type.Bool
导入的(或者我可以使用PolyKind来实现)...
但是f2
未编译,出现类似错误
• Couldn't match type ‘TL2Fun
(If
(IsMark Int)
(If
(IsMark Int)
(If (IsMark Int) '[] '[Int])
(Int : If (IsMark Int) '[] '[Int]))
(Int
: If
(IsMark Int)
(If (IsMark Int) '[] '[Int])
(Int : If (IsMark Int) '[] '[Int])))’
with ‘a0 -> a0 -> a0’
Expected type: TL2Fun (WOMarks '[Int, Int, Int, Uniq])
Actual type: a0 -> a0 -> a0
The type variable ‘a0’ is ambiguous
• The equation(s) for ‘f2’ have two arguments,
but its type ‘TL2Fun (WOMarks '[Int, Int, Int, Uniq])’ has none (intero)
我的过滤尝试中似乎存在If
的:它是“调用”树,但尚未对过滤结果进行“评估”(或其他原因,我不确定错误原因)。如何实现我的目标,即通过谓词删除类型?
答案 0 :(得分:3)
@ M.Aroosi指出,\1,\2,\3,\4,\5,\6,\7 \8
需要一个IsMark
的实例:
Int
,然后程序将键入check。当然,您不需要为每种非标记类型都定义一个实例,并使用:
type instance IsMark Int = 'False
将导致实例冲突。
解决方案是改为定义封闭类型族:
type instance IsMark a = 'False
在此之后一切正常:
type family IsMark a :: Bool where
IsMark Uniq = 'True
IsMark NUniq = 'True
IsMark UUniq = 'True
IsMark a = 'False