让我们说我有无限的动作序列,每个动作都返回某种类型的结果。类似的东西:
newtype Stream a = Stream (IO (a, Stream a))
但a
会随着时间而变化。我想强烈输入这个序列。对于任意无限类型序列和天真的方法来说,显然不会产生这样的结果:
data HStream :: [u] -> * where Cons :: Proxy x -> HStream xs -> HStream (x ': xs)
infiniteInt = Cons (Proxy :: Proxy Int) infiniteInt
将导致无限类型,Haskell的类型系统不支持。但是我没有看到最终周期性的HLists没有任何问题(即,从某个点开始重复自己的类型序列:[Bool, Int, Int, Sting, Int, Sting, Int, Sting ... ]
)。而且我还认为,如果我们有一些强烈规范化的方式来描述无限类型或某种方式来提供无限类型相等的证据,可以在有限数量的步骤中进行检查,那么应该可以用这种无限类型来检查程序。 / p>
有谁知道如何在Haskell中表示和使用这些类型?现在让我们从无限的最终周期hlist开始,但是如果有人知道如何将它推广到更广泛的无限类型以及泛化限制的范围,我也会感激。
答案 0 :(得分:5)
使用这个One Cool Trick让HList
无限且周期性!
向定期异构流添加元素时,请不要扩展其索引类型列表。旋转它。
type family Append x xs where
Append x '[] = '[x]
Append x (y ': xs) = y ': Append x xs
infixr 5 :::
data HStream as where
(:::) :: { headHS :: a, tailHS :: HStream (Append a as) } -> HStream (a ': as)
myHStream :: HStream '[Char, Bool, Int]
myHStream = 'c' ::: True ::: 3 ::: 'x' ::: False ::: -5 ::: myHStream
答案 1 :(得分:1)
一个通用选项是从编码所有元素类型的HList
切换到类型对齐列表(或者更一般地,类型对齐的序列),这只能确保转换顺序有效路径。
data TAList c x z where
Nil :: TAList c x x
Cons :: c x y -> TAList c y z -> TAList c x z
因此,您可以谨慎地对转场进行编码,使用c
的可能性较大的GADT以及x
和z
的适当选择。无限类型对齐列表没有问题,因为它们在最终类型参数中具有多态性。
您可以使用McBride风格的索引方案而不是Atkey方案来获得更大的灵活性,但代价是更复杂。