Haskell用符号绑定

时间:2013-06-06 14:27:09

标签: haskell do-notation

我正试图在Haskell中去做一个do语句。我在这里找到了一些例子但是不能将它们应用到我的案例中。 我唯一能想到的是一个沉重的嵌套let语句,看起来很难看。

应该用bind替换表示法的语句:

do num <- numberNode x
   nt1 <- numberTree t1
   nt2 <- numberTree t2
   return (Node num nt1 nt2)

高度赞赏任何输入=)

3 个答案:

答案 0 :(得分:13)

numberNode x >>= \num ->
  numberTree t1 >>= \nt1 ->
    numberTree t2 >>= \nt2 ->
      return (Node num nt1 nt2)

请注意,如果您使用Applicatives,这会更简单:

Node <$> numberNode x <*> numberTree t1 <*> numberTree t2

答案 1 :(得分:8)

这是applicative style的一个很好的用例。您可以使用

替换整个代码段(在导入Control.Applicative之后)
Node <$> numberNode x <*> numberTree t1 <*> numberTree t2

将应用样式(使用<$><*>)视为“提升”函数应用程序,以便它也适用于仿函数。如果你在心理上忽略<$><*>,它看起来就像普通的功能应用程序一样!

只要你有一个纯函数并且你想给它不纯的参数(或任何函子参数,实际上),应用风格很有用 - 基本上当你想要做你在问题中指定的内容时!


<$>的类型签名是

(<$>) :: Functor f => (a -> b) -> f a -> f b

这意味着它需要一个纯函数(在本例中为Node)和一个函子值(在本例中为numberNode x),它会创建一个包含在“函数内部”的新函数。您可以使用<*>向此函数添加更多参数,其中包含类型签名

(<*>) :: Applicative f => f (a -> b) -> f a -> f b

正如您所看到的,这与<$>非常相似,只有当函数被“包含在”函数内部时才会起作用。

答案 2 :(得分:2)

我想在上面添加有关Applicative的帖子..

考虑<$>的类型:

(<$>) :: Functor f => (a -> b) -> f a -> f b

它看起来就像fmap:

fmap :: Functor f => (a -> b) -> f a -> f b

这也非常像Control.Monad.liftM:

liftM :: Monad m => (a -> b) -> m a -> m b

我认为这是“我需要将数据构造函数提升到这种类型”

在相关的说明中,如果您发现自己这样做:

action >>= return . f

你可以这样做:

f `fmap` action

第一个例子是使用bind从任何类型的动作中取出值,用它调用f,然后重新打包结果。相反,我们可以解除f,以便将行动类型作为其论据。