我需要爲我正在處理的東西實現一個通用堆棧。這個堆棧應該能夠保存不同類型的元素。例如(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