【发布时间】:2023-03-12 23:33:01
【问题描述】:
所以我最近想出了这个巧妙的想法,希望在严格和懒惰的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 的 Monad 实例:
-- 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
然后我可以在Lazy 或Strict 实例化t 并运行结果并得到我期望的结果。但是为什么我必须给出这个背景呢?这是一个概念上的限制,还是一个实际的限制?有什么原因我错过了为什么Monad (State t s a) 实际上不成立,还是没有办法让 GHC 相信它?
(除此之外:使用上下文 Monad (State t s) 不起作用:
Could not deduce (Monad (State t [Bool])) arising from a do statementfrom the context (Monad (State t s))
这让我更加困惑。前者肯定可以从后者推导出来吧?)
【问题讨论】:
-
确实是
DataKinds的限制。我看到发生了一些相关的事情,GHC 无法确定带有DataKinds的 GADT 的模式是详尽无遗的,并且它生成的建议不会进行类型检查。
标签: haskell data-kinds