【发布时间】:2012-05-27 21:04:55
【问题描述】:
我正在开发一个库,我想在其中定义一个已在此处简化为的递归类:
{-# LANGUAGE MultiParamTypeClasses
, FlexibleInstances #-}
data Snoc st b c = Snoc (st b) (c -> b)
data Top a = Top
class StackTo a st c where
runStack :: st c -> (c -> a)
instance StackTo a Top a where
runStack _ = id
instance (StackTo a st b) => StackTo a (Snoc st b) c where
runStack (Snoc st' cb) = runStack st' . cb
这让我可以做,例如
*Main Data.Label> let f = runStack $ Snoc (Snoc Top fst) head :: [(a,x)] -> a
*Main Data.Label> f [('a',undefined)]
'a'
但这似乎需要小心使用类型注解,否则……
*Main Data.Label> let f = runStack $ Snoc (Snoc Top fst) head
<interactive>:1:1:
No instance for (StackTo a0 Top b0)
arising from a use of `runStack'
Possible fix: add an instance declaration for (StackTo a0 Top b0)
In the expression: runStack
In the expression: runStack $ Snoc (Snoc Top fst) head
In an equation for `it': it = runStack $ Snoc (Snoc Top fst) head
我认为这些问题与 this question 中解决的问题相同,但我无法在此处调整该解决方案。我可以使用类型族或其他方法为我的递归延续堆栈提供更用户友好的解决方案吗?
【问题讨论】:
-
您可能想考虑只使用
class Stack st与type Domain st a和type Codomain st a之类的关联类型或类似的东西,但我没有仔细阅读以知道这是否适用你。
标签: haskell typeclass type-families