【发布时间】:2021-09-14 15:55:46
【问题描述】:
因此,可以像这样定义成员约束:
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE GADTs #-}
module Whatever where
type family MemberB (x :: k) (l :: [k]) where
MemberB _ '[] = 'False
MemberB a (a : xs) = 'True
MemberB a (b : xs) = MemberB a xs
type Member x xs = MemberB x xs ~ 'True
data Configuration = A | B | C
data Action (configuration :: Configuration) where
Action1 :: Member cfg '[ 'A ] => Action cfg
Action2 :: Member cfg '[ 'B, 'C ] => Action cfg
Action3 :: Member cfg '[ 'A, 'C ] => Action cfg
exhaustive :: Action 'A -> ()
exhaustive Action1 = ()
exhaustive Action3 = ()
exhaustive Action2 = ()
但是我们得到的错误信息不是很丰富:
• Couldn't match type ‘'False’ with ‘'True’
Inaccessible code in
a pattern with constructor:
Action2 :: forall (cfg :: Configuration).
Member cfg '['B, 'C] =>
Action cfg,
in an equation for ‘exhaustive’
• In the pattern: Action2
In an equation for ‘exhaustive’: exhaustive Action2 = () (intero)
最好使用新的TypeError 功能来改进此消息,但是,一个天真的解决方案会吞噬错误:
import GHC.TypeLits
type family MemberB (x :: k) (l :: [k]) where
MemberB _ '[] = TypeError ('Text "not a member")
MemberB a (a : xs) = 'True
MemberB a (b : xs) = MemberB a xs
似乎TypeError 的行为与任何类型一样,因此它与'True 愉快地统一了?
有没有办法得到一个不错的类型错误,同时保留成员行为?
【问题讨论】:
-
我确实得到了错误:
29:7: error: • not a member • In the expression: foo In an equation for ‘bar’: bar = foo -
哇,也许我应该更新我的 GHC!?让我检查一下!
-
哈,我把问题简单化了,现在更新它......
-
@dfeuer ha,我更新了代码,但没有更新错误信息,现在已修复
标签: haskell type-constraints type-families