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

type SnapApp a = StateT AppState Snap a

这在模块中定义,例如Base。由于在其他模块中需要它,因此必须将其导出:
module Base
  ( ..
  , SnapApp
  ) where

很好,但是我希望该模块不导出SnapApp是状态monad,因为我需要进行一些复杂的处理来设置状态的某些属性。例如,会话。我必须在更改文件时写入文件,因此仅getput修改的会话是错误的,应调用特殊功能。因此,我使用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 aStateT AppState Snap a
  • 参数a -> SnapApp ba -> StateT AppState Snap b
  • 结果StateT AppState Snap bSnapApp b

  • 1)使用模式匹配;定义:
    fromSnapApp (SnapApp x) = x
    

    2)编写函数a -> SnapApp bSnapApp 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)
    

    10-06 10:30