康纳麦克布莱德和罗斯帕特森的经典论文 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''
(使用非确定性计算
列表的观点)似乎与矢量无关
转置。
换句话说,transpose
和transpose''
似乎无关
功能 - 不同的例子。我错过了什么吗?
答案 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 _ _ = []