3

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

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 吗?

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

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

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

这种方法不适用于 Haskell 编程?我应该改变我的思维模型吗?还是我对 Haskell 有误解?

4

2 回答 2

8

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

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

然后

plusOne = fmap (+1)

plusOne' = fmap $ liftM (+1)

但是,现在我突然想到我可能误解了这个问题......

于 2013-03-29T00:43:06.500 回答
7

First things first, it looks like you've actually redefined the Identity monad.

When you have functors containing other functors as you do here, you don't want to have to do all the bookkeeping yourself to make sure you've got the right number of fmaps and so on. That's where monad transformers come in.

The MTL library (which should come with the Haskell Platform) has done all the hard work for you, you just need to do a bit (OK, quite a lot) of plumbing to make your own type work with all the existing monad transformers. Once you've done that, your Container should be a good citizen as a member of any monad stack.

Of course, the usual caveats apply: monad transformers are powerful and hard to understand. Half the times you think you need them, you don't really - so make sure you're using the right approach to solve your problem first.

于 2013-03-29T01:23:08.330 回答