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

时间:2013-03-29 00:07:48

标签: haskell

我是Haskell的新手。我正在学习monads。

data Container a = Container a deriving Show

x = Container 1 :: Container Int

plusOne :: Container Int -> Container Int
plusOne (Container x) = Container (x+1)

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

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

plusOne' :: Container (IO Int) -> Container (IO Int)  
plusOne' (Container x) = Container (liftM (+1) x)

全部谢谢:-) 那有没有办法避免重新定义plusOne?

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

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

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

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

2 个答案:

答案 0 :(得分:7)

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

instance Functor Container where
    fmap f (Container a) = Container (f a)

然后

plusOne = fmap (+1)

plusOne' = fmap $ liftM (+1)

然而,现在我发现我可能误解了这个问题......

答案 1 :(得分:6)

首先,看起来您实际上已经重新定义了the Identity monad

如果您在此处使用包含其他仿函数的仿函数,则您不希望自己完成所有记账,以确保您拥有正确数量的fmap等等。这就是monad transformers进来的地方。

The MTL library(应该随Haskell平台一起提供)已经为你完成了所有艰苦的工作,你只需要做一些(好的,很多)管道工作,让你自己的类型与所有人一起工作现有的monad变形金刚。一旦你完成了这一点,你的Container应该是一个好公民,作为任何monad堆栈的成员。

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