我该怎么称呼这个功能?我需要一个返回元组的函数

时间:2014-06-21 01:30:13

标签: haskell

我对此代码有一个问题:

append (first, second) f  = (first ++ fst(f second), snd(f second))
                                      ^^^^^^^^^^^^^  ^^^^^^^^^^^^^

我不知道如何调用此功能,因为我不了解如何正确匹配^标记的功能。在我看来,我需要一个返回元组的函数,因为函数fst需要这个。

1 个答案:

答案 0 :(得分:6)

如果用显式模式匹配和共享重写一下你的表达式,事情会变得更加清晰:

append :: ([w], a) -> (a -> ([w], b)) -> ([w], b)
append (w, a) f  = let (w', b) = f a
                   in  (w ++ w', b)

因此,您使用列表和值获取元组,应用生成另一个列表的函数。该列表将附加到原始列表中,该值将替换元组中的前一个列表。

似乎你重新发明了((,) w) monad又名作家monad!

查看>>=(绑定)的类型,它将一个函数应用于生成另一个monadic值的momadic值:

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

现在,如果您将m替换为((,) w)(或(w,),如果类型中允许使用元组部分的表示法),则m a成为(w, a) ,你得到:

bindSpecialized :: (w, a) -> (a -> (w, b)) -> (w, b)

但是如果我们有办法合并((,) w)w只能用作monad。您通过列表和++实现了这一目标。更通用的方法是将类型类Monoid用于具有关联操作和标识元素的类型。

由于某些原因,((,) w)不是前奏中定义的monad,建议使用newtype:

newtype Writer w a = Writer { runWriter :: (w, a) }

instance Functor (Writer w) where
  fmap f (Writer (w, a)) = Writer (w, f a)

instance Monoid w => Monad (Writer w) where
  return a = Writer (mempty, a)
  (Writer (w, a)) >>= f = let Writer (w', b) = f a
                          in  Writer (w <> w', b)

tell :: Monoid w => w -> Writer w ()
tell w = Writer (w, ())

-- test == ("hello world", 3)
test :: (String, Int)
test = runWriter $ do
    a <- test1
    b <- test2
    return $ a + b
  where
    test1 = tell "hello" >> return 1
    test2 = tell " world" >> return 2

对于实际程序,您应该使用Writer中已定义的{{1}}类型及其monad实例。