所以我最近這個不錯的主意想出了所有的情況下,在共享代碼的嚴格和懶惰State
變壓器模塊之間的希望:覆蓋可提升數據類型
{-# LANGUAGE FlexibleInstances, DataKinds, KindSignatures #-}
module State where
data Strictness = Strict | Lazy
newtype State (t :: Strictness) s a = State (s -> (s, a))
returnState :: a -> State t s a
returnState x = State $ \s -> (s, x)
instance Monad (State Lazy s) where
return = returnState
State ma >>= amb = State $ \s -> case ma s of
~(s', x) -> runState (amb x) s'
instance Monad (State Strict s) where
return = returnState
State ma >>= amb = State $ \s -> case ma s of
(s', x) -> runState (amb x) s'
get :: State t s s
get = State $ \s -> (s, s)
put :: s -> State t s()
put s = State $ \_ -> (s,())
你可以看到,get
和put
兩者都在沒有任何重複的情況下工作 - 對於嚴格類型和惰性類型都沒有類型實例,也沒有任何重複類型。然而,即使我涵蓋Strictness
兩種可能的情況下,我不一般都有一個單子實例State t s a
:
-- from http://blog.melding-monads.com/2009/12/30/fun-with-the-lazy-state-monad/
pro :: State t [Bool]()
pro = do
pro
s <- get
put (True : s)
-- No instance for (Monad (State t [Bool])) arising from a do statement
下工作得很好,儘管需要FlexibleContexts
:
pro :: (Monad (State t [Bool])) => State t [Bool]()
-- otherwise as before
然後我可以實例化t
在Lazy
或Strict
並運行結果並得到我所期望的結果。但爲什麼我必須提供這樣的背景?這是一個概念上的限制,還是一個實際的限制?有沒有什麼理由我錯過了爲什麼Monad (State t s a)
實際上不成立,還是沒有辦法說服GHC呢?
(旁白:使用上下文Monad (State t s)
不工作:
Could not deduce (Monad (State t [Bool])) arising from a do statement
from the context (Monad (State t s))
這只是混淆我更加肯定前者是後者的抵扣?)
這確實是'DataKinds'的一個限制。我看到一些相關的事情發生,GHC無法弄清楚'DataKinds'的GADT模式是否詳盡,並且產生了不會進行類型檢查的建議。 – 2013-01-11 00:31:27