Haskell 定义了一个类型族(+;+;);有没有办法证明(与我们相比)&+;x27;[]意味着(vs~';[])和(us~';[])?
定义:Haskell 定义了一个类型族(+;+;);有没有办法证明(与我们相比)&+;x27;[]意味着(vs~';[])和(us~';[])?,haskell,functional-dependencies,type-families,Haskell,Functional Dependencies,Type Families,定义: type family (xs :: [*]) ++ (ys :: [*]) where '[] ++ ys = ys (x ': xs) ++ ys = x ': (xs ++ ys) 我有一个有点像 data Foo :: [*] -> * -> * where Foo0 :: a -> Foo '[] a Foo1 :: Foo '[a] a Foo2 :: Foo vs a -> Foo us a -> Foo (vs ++ u
type family (xs :: [*]) ++ (ys :: [*]) where
'[] ++ ys = ys
(x ': xs) ++ ys = x ': (xs ++ ys)
我有一个有点像
data Foo :: [*] -> * -> * where
Foo0 :: a -> Foo '[] a
Foo1 :: Foo '[a] a
Foo2 :: Foo vs a -> Foo us a -> Foo (vs ++ us) a
我想做一些类似的事情
test :: Foo '[] Int -> Int
test (Foo0 x) = x
test (Foo2 x y) = test x + test y
但是我不能在x
或y
上使用test
,因为x~Foo'[]Int
和y~Foo'[]Int
必须经过验证。但是我想说的是,事实证明了这一点,vs++us~'[]
意味着vs
和us
中的x
和y
的个体必然是'[]
有没有办法用类型族实现这一点,或者用fundeps切换到多参数类型类方法
谢谢
返回类型中存在“green slime”定义的函数
对施工人员来说,这是一个危险的标志
最简单的解决方法是概括测试
,然后实例化:
gtest :: Foo xs Int -> Int
gtest (Foo0 x) = x
gtest (Foo2 x y) = gtest x + gtest y
test :: Foo '[] Int -> Int
test = gtest
您可以添加两个类型族,作为
++
的逆类型,并在不丧失通用性的情况下将它们作为约束添加到Foo2构造函数中。通过这些反向类型的族,GHC将能够准确地推断出您从中提出的要求
下面是CutX
和CutY
的示例实现,这样ra++b
a~CutY rb
b~CutX ra
type family (xs :: [*]) ++ (ys :: [*]) where
'[] ++ ys = ys
(x ': xs) ++ ys = x ': (xs ++ ys)
type family CutX (rs :: [*]) (xs :: [*]) where
CutX '[] xs = '[]
CutX rs '[] = rs
CutX (r ': rs) (x ': xs) = CutX rs xs
type family ZipWithConst (xs :: [*]) (ys :: [*]) where
ZipWithConst '[] ys = '[]
ZipWithConst xs '[] = '[]
ZipWithConst (x ': xs) (y ': ys) = y ': ZipWithConst xs ys
type CutY rs ys = ZipWithConst rs (CutX rs ys)
data Foo :: [*] -> * -> * where
Foo0 :: a -> Foo '[] a
Foo1 :: Foo '[a] a
Foo2 :: (rs ~ (vs ++ us), us ~ CutX rs vs, vs ~ CutY rs us) => Foo vs a -> Foo us a -> Foo rs a
如果
[*]
索引始终等于[*]
,为什么还要在Foo
GADT中使用它呢?假设有另一个构造函数:)您还可以包括其他构造函数吗?当前的一组构造函数使我们的工作变得相当简单(参考下面的user3237465的答案)。@AndrásKovács啊,我明白你的意思。我又加了一个。。。这有区别吗?@AndrásKovács可能是以前从未使用过。不久前我自己发现了它并写了一篇文章。