我需要为我正在处理的东西实现一个通用堆栈。这个堆栈应该能够保存不同类型的元素。例如(1,'c',True,“字符串”)。要支持的功能是top,pop和push。Haskell中的一般'无类型'堆栈
元组是最自然的想法。
push x s = (x,s)
pop s = snd s
top s = (fst s, s)
但我也需要支持空栈。这里,pop和top没有在()上定义。 所以我尝试创建一个新类型。
data Stack = Empty | forall x. Cons (x, Stack)
push x s = Cons (x,s)
pop s = case s of
Empty -> Left s
Cons (x, y) -> Right y
top s = case s of
Empty -> (Left(), s)
Cons (x,y) -> (Right x, s)
这里,顶给我一个错误:
Couldn't match expected type ‘b’ with actual type ‘x’
because type variable ‘x’ would escape its scope
This (rigid, skolem) type variable is bound by
a pattern with constructor
Cons :: forall x. (x, Stack) -> Stack,
in a case alternative
at try.hs:11:9-18
Relevant bindings include
x :: x (bound at try.hs:11:15)
top :: Stack -> (Either() b, Stack) (bound at try.hs:9:1)
In the first argument of ‘Right’, namely ‘x’
In the expression: Right x
如果我解决这个具有:
data Stack x = Empty | forall y. Cons (x, Stack y)
我得到同样的错误弹出。
我也尝试添加此:
type AnyStack = forall x. Stack x
但同样得到类似的错误:
Couldn't match expected type ‘b’ with actual type ‘Stack y’
because type variable ‘y’ would escape its scope
This (rigid, skolem) type variable is bound by
a pattern with constructor
Cons :: forall x y. (x, Stack y) -> Stack x,
in a case alternative
at try.hs:8:9-19
Relevant bindings include
y :: Stack y (bound at try.hs:8:18)
pop :: Stack t -> Either (Stack t) b (bound at try.hs:6:1)
In the first argument of ‘Right’, namely ‘y’
In the expression: Right y
谁能帮我出正确的类型签名或类型定义为这种堆叠?或者,也许可以指点一下与此有关的一些很好的参考?
非常感谢先进!
编辑:
这将会是完美的,如果我还能够包括对于这种叠层get函数。给定一个整数i和一个堆栈s,get会返回s的第i个元素。我希望我能够在推动,弹出和顶部排序后自己做到这一点,但我仍然无法做到。关于这个家伙的任何想法?
谢谢!这是一个相当惊人的实现! – 2014-11-23 07:21:37
如果我也能够为这个堆栈包含get函数,那将是完美的。给定一个整数i和一个堆栈s,get会返回s的第i个元素。我希望我能够在推动,弹出和顶部排序后自己做到这一点,但我仍然无法做到。有关这个的任何想法? – 2014-11-23 07:58:18
@ shivanker.goel这个东西很容易被这个实现管理。如果只在编译时确定索引,这并不是什么坏事,但如果可以在运行时选择索引,这是非常困难的。那时,这在Haskell中基本上不可行。 – Carl 2014-11-23 17:47:47