如何解除应用monadic值容器的功能?

Poc*_*878 2 haskell

我是Haskell的新手.我正在学习单子.

data Container a = Container a deriving Show

x = Container 1 :: Container Int

plusOne :: Container Int -> Container Int
plusOne (Container x) = Container (x+1)
Run Code Online (Sandbox Code Playgroud)

有没有办法解除plusOne申请Container (IO Int)

或者我应该定义一个新功能,例如:

plusOne' :: Container (IO Int) -> Container (IO Int)  
plusOne' (Container x) = Container (liftM (+1) x)
Run Code Online (Sandbox Code Playgroud)

谢谢大家:-)然后有什么方法可以避免重新定义plusOne吗?

因为我构建程序,首先我用非monadic类型的容器构建程序(正常值如:Container Int ..etc),并且我测试具有指定值的函数(容器10 ..).

然后我尝试将这些程序应用于随机或生成的值.这是我用其他语言编程的基本方法(比如Lisp,Python ..)

所以当我想尝试将这些函数应用于monadic-value容器时,我不想重新定义函数.

这种方法不适用于Haskell编程?我应该改变我的思维模式吗?或者我误解了Haskell?

Kot*_*lar 7

看起来Container应该是Functor的一个实例:

instance Functor Container where
    fmap f (Container a) = Container (f a)
Run Code Online (Sandbox Code Playgroud)

然后

plusOne = fmap (+1)
Run Code Online (Sandbox Code Playgroud)

plusOne' = fmap $ liftM (+1)
Run Code Online (Sandbox Code Playgroud)

但是,现在我发现我可能误解了这个问题......

  • 您可以使用`DeriveFunctor`语言扩展派生`Functor`.另外,键入类态射风格:`(fmap.fmap)(+ 1)` (2认同)

Ben*_*son 6

首先,看起来你实际上已经重新定义Identitymonad.

当你在这里有包含其他仿函数的仿函数时,你不希望自己做所有的记账,以确保你有正确数量的fmaps等等.这就是monad变形金刚进来的地方.

MTL库(它应该随Haskell平台一起提供)已经为您完成了所有艰苦的工作,您只需要做一些(好的,相当多)管道,使您自己的类型与所有现有的monad变换器一起工作.一旦你做完了,你Container应该是一个好公民作为任何monad堆栈的成员.

当然,通常的警告适用:monad变形金刚强大且难以理解.有一半你认为你需要它们,你不是真的 - 所以要确保你使用正确的方法来解决你的问题.