让我从我要解决的任务开始,可能我走错了路。我将Snap框架用于玩具项目,主要是它在Snap
monad下起作用。我需要在上面添加我的状态。我使用monad变压器:
type SnapApp a = StateT AppState Snap a
这在模块中定义,例如
Base
。由于在其他模块中需要它,因此必须将其导出:module Base
( ..
, SnapApp
) where
很好,但是我希望该模块不导出
SnapApp
是状态monad,因为我需要进行一些复杂的处理来设置状态的某些属性。例如,会话。我必须在更改文件时写入文件,因此仅get
和put
修改的会话是错误的,应调用特殊功能。因此,我使用newtype
而不是数据导出construstor来隐藏它:newtype SnapApp a = SnapApp (StateT AppState Snap a)
我使用修改会话等功能将其作为类的实例。但是出现了问题:我丢失了
Monad
类的实例,而丢失了新SnapApp
的实例。而且我坚持实现>>=
:instance Monad SnapApp where
return = SnapApp . return
mx >>= fm = -- HOW?
谢谢!
最佳答案
让类型指导您。
你需要
(>>=) :: SnapApp a -> (a -> SnapApp b) -> SnapApp b
你有
(>>=) :: StateT AppState Snap a -> (a -> StateT AppState Snap b) -> StateT AppState Snap b
您需要转换:
SnapApp a
到StateT AppState Snap a
a -> SnapApp b
到a -> StateT AppState Snap b
StateT AppState Snap b
到SnapApp b
1)使用模式匹配;定义:
fromSnapApp (SnapApp x) = x
2)编写函数
a -> SnapApp b
和SnapApp b -> StateT AppState b
3)使用
SnapApp
最后结果:
x >>= f = SnapApp (fromSnapApp x >>= (fromSnapApp . f))
要么:
SnapApp x >>= f = SnapApp (x >>= (fromSnapApp . f))
您不必写这个;如果启用
GeneralizedNewtypeDeriving
扩展名,GHC可以派生该实例:newtype SnapApp a = SnapApp (StateT AppState Snap a) deriving (Monad)