请求澄清McBride / Paterson申请文件中的换位示例

时间:2014-03-29 17:45:27

标签: haskell monads

康纳麦克布莱德和罗斯帕特森的经典论文 Applicative programming with effects 显示'matrice'换位示例:

transpose   :: [[a]] -> [[a]]
transpose [] = repeat []
transpose (xs : xss) = zipWith (:) xs (transpose xss)

transpose正在使用列表的“收集视角”:它成对 函数(此处为(:))并按元素输入并生成结果列表 输出。

因此,给定

v = [[1,2,3],[4,5,6]]

然后

transpose  v

结果

[[1,4],[2,5],[3,6]]

他们在论文的后面说了

如果我们想为我们的转置示例做同样的事情,我们必须这样做 避免图书馆的“成功列表”(Wadler,1985)monad and take 而是一个支持'矢量化'的实例Applicative [], 其中pure = repeat(~) = zapp,屈服于

transpose'' :: [[a]] -> [[a]]
transpose''         [] = pure []
transpose'' (xs : xss) = pure (:) <*> xs <*> transpose'' xss

这里,transpose''正在使用“非确定性计算点 列表的视图:它将函数(此处为(:))应用于输入 转动。

因此

 transpose'' v

结果

 [[1,4],[1,5],[1,6],[2,4],[2,5],[2,6],[3,4],[3,5],[3,6]]

我觉得我错过了一些微妙的观点。我可以看到transpose是 确实使用收集的角度来转置“向量” 名单。但transpose''(使用非确定性计算 列表的观点)似乎与矢量无关 转置。

换句话说,transposetranspose''似乎无关 功能 - 不同的例子。我错过了什么吗?

2 个答案:

答案 0 :(得分:2)

  

其中pure = repeat(❄) = zapp,产生......

这是标准列表实例。要在Haskell中实现这一点,我们需要

newtype Zapp a = Zapp { runZapp : [a] } deriving (Functor)
zcons :: a -> Zapp a -> Zapp a
zcons x (Zapp xs) = Zapp $ x : xs

instance Applicative Zapp where
  pure = Zapp . repeat
  Zapp a <*> Zapp b = Zapp $ zapp a b

然后

transpose'' :: Zapp (Zapp a) -> Zapp (Zapp a)
transpose''         (Zapp []) = pure $ Zapp []
transpose'' (Zapp (xs : xss)) = pure zcons <*> xs <*> transpose'' xss

答案 1 :(得分:1)

如果您为第一个示例列出了实例,那么Applicative实例有pure = repeat<*> = zapp

instance Applicative [] where
    pure = repeat
    (<*>) = zapp

transpose :: [[a]] -> [[a]]
transpose         [] = pure []
transpose (xs : xss) = pure (:) <*> xs <*> transpose xss

main = do
    print . transpose $ [[1,2,3],[4,5,6]]

你从转置获得转置:

[[1,4],[2,5],[3,6]]

相反,如果您使用Applicative

的普通[]实例
instance Applicative [] where
    pure x = [x]
    fs <*> xs = [f x | f <- fs, x <- xs]

transpose :: [[a]] -> [[a]]
transpose         [] = pure []
transpose (xs : xss) = pure (:) <*> xs <*> transpose xss

main = do
    print . transpose $ [[1,2,3],[4,5,6]]

你得到了

[[1,4],[1,5],[1,6],[2,4],[2,5],[2,6],[3,4],[3,5],[3,6]]

这两个例子的样板是:

module Main (
    main
) where

import Prelude hiding (repeat)

infixl 4 <*>
class Applicative f where
    pure :: a -> f a
    (<*>) :: f (a -> b) -> f a -> f b

repeat :: a -> [a]
repeat x = x : repeat x

zapp :: [a -> b] -> [a] -> [b]
zapp (f : fs) (x : xs) = f x : zapp fs xs
zapp _        _        = []