我有以下代码段:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeInType #-}
import Data.Proxy
data Foo where
FooInt :: Foo
FooProxy :: IsEnum e ~ True => Proxy e -> Foo
type family IsEnum e :: Bool
type family FromFoo (foo :: Foo) where
FromFoo FooInt = Int
FromFoo (FooProxy ('Proxy :: Proxy e)) = e
一般的想法是我正在尝试使用Foo
作为我可以做的数据类型
type MyFoo1 = FooInt :: Foo
type instance IsEnum Bool = True
type MyFoo2 = FooProxy ('Proxy :: Proxy Bool) :: Foo
,并确保传递给FooProxy
的代理类型是IsEnum
类型家族的一部分(我不能只做FooProxy :: Enum e => Proxy e -> Foo
,因为only equality constraints are currently supported)。 / p>
但是当我尝试编译它时,出现错误:
<interactive>:30:12: error:
• Couldn't match expected kind ‘'True’ with actual kind ‘IsEnum e’
• In the first argument of ‘FromFoo’, namely
‘(FooProxy ( 'Proxy :: Proxy e))’
In the type family declaration for ‘FromFoo’
问题是,当我想从我的Foo
类型转换为FromFoo
中的具体类型时,我希望FooProxy
评估为代理类型。因此,我尝试在Proxy
上进行模式匹配以返回代理类型e
,但随后似乎再次检查了IsEnum e ~ True
约束。我认为仅在创建一个FooProxy
值时才检查约束,但是在模式匹配时似乎要再次检查约束。