在newtype中实现>> =

dem*_*emi 3 monads haskell instance typeclass

让我从我想解决的任务开始,可能是我走错了路.我将Snap框架用于玩具项目,主要是它在Snapmonad 下的功能.我需要在它上面添加我的状态.我用monad变压器:

type SnapApp a = StateT AppState Snap a
Run Code Online (Sandbox Code Playgroud)

例如,这在模块中定义Base.由于我在其他模块中需要它,我必须导出它:

module Base
  ( ..
  , SnapApp
  ) where
Run Code Online (Sandbox Code Playgroud)

这很好,但我希望该模块不会导出SnapApp状态monad,因为我有一些复杂的处理来为状态设置一些属性.例如,会话.我有当它变以写入文件,因此它不应当只是getput修改的会话,特殊功能应该被调用.所以,我隐藏了使用newtype而不是数据导出construstor:

newtype SnapApp a = SnapApp (StateT AppState Snap a)
Run Code Online (Sandbox Code Playgroud)

我创建了我的类的实例,其中包含用于修改会话等的函数.但问题出现了:我丢失了Monad类和其他类的实例SnapApp.我坚持执行>>=:

instance Monad SnapApp where
    return = SnapApp . return
    mx >>= fm = -- HOW?
Run Code Online (Sandbox Code Playgroud)

谢谢!

sdc*_*vvc 16

让类型指导你.你需要

(>>=) :: SnapApp a -> (a -> SnapApp b) -> SnapApp b
Run Code Online (Sandbox Code Playgroud)

你有

(>>=) :: StateT AppState Snap a -> (a -> StateT AppState Snap b) -> StateT AppState Snap b
Run Code Online (Sandbox Code Playgroud)

你需要转换:

  • 争论SnapApp aStateT AppState Snap a
  • 争论a -> SnapApp ba -> StateT AppState Snap b
  • 结果StateT AppState Snap bSnapApp b

1)使用模式匹配; 限定:

fromSnapApp (SnapApp x) = x
Run Code Online (Sandbox Code Playgroud)

2)撰写功能a -> SnapApp bSnapApp b -> StateT AppState b

3)使用 SnapApp

最后结果:

x >>= f = SnapApp (fromSnapApp x >>= (fromSnapApp . f)) 
Run Code Online (Sandbox Code Playgroud)

要么:

SnapApp x >>= f = SnapApp (x >>= (fromSnapApp . f)) 
Run Code Online (Sandbox Code Playgroud)

你不必写这个; 如果启用GeneralizedNewtypeDeriving扩展,GHC可以派生实例:

newtype SnapApp a = SnapApp (StateT AppState Snap a) deriving (Monad)
Run Code Online (Sandbox Code Playgroud)