我正在从 Control.Monad.Product 包构建一些产品单子。作为参考,产品单子类型为:
newtype Product g h a = Product { runProduct :: (g a, h a) }
它的 monad 实例是:
instance (Monad g, Monad h) => Monad (Product g h) where
return a = Product (return a, return a)
Product (g, h) >>= k = Product (g >>= fst . runProduct . k, h >>= snd . runProduct . k)
Product (ga, ha) >> Product (gb, hb) = Product (ga >> gb, ha >> hb)
问题一
我构建了一个简单的 monad,它是两个State Int
Monad 的乘积,但是,当我接下来尝试访问底层状态时:
ss :: Product (State Int) (State Int) Int
ss = do
let (a,b) = unp $ P.Product (get,get) :: (State Int Int,State Int Int)
return 404
你看get
只是创建了另一个State Int Int
,我不确定如何实际获得底层状态的值,我该怎么做?请注意,我可能会获得潜在runState
a
的b
价值,但这个解决方案似乎不是很有用,因为这两个状态的初始值必须先验地固定。
问题二。
我真的很希望能够在不同类型的状态下创建一个产品单子,即:
ss2 :: Product (State Int) (State String) ()
ss2 = do
let (a,b) = unp $ P.Product (get,get) :: (State Int Int,State Int String)
return ()
但我收到这种类型的错误:
Couldn't match expected type `String' with actual type `Int'
Expected type: (State Int Int, State String String)
Actual type: (StateT Int Identity Int,
StateT String Identity Int)
因为我认为两者get
必须返回相同的类型,这是一个不幸的限制。关于如何解决这个问题的任何想法?