微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

haskell – Canonical外部连接拉链功能

如果将列表中每个元素的(隐式)索引视为其键,则zipwith有点像关系内连接.它只处理两个输入都具有值的键:
zipwith (+) [1..5] [10..20] == zipwith (+) [1..11] [10..14] == [11,13,15,17,19]

是否存在与外连接对应的规范对应函数?就像是:

outerZipwith :: (a -> b -> c) -> a -> b -> [a] -> [b] -> [c]
outerZipwith _ _ _ [] [] = []
outerZipwith f a' b' [] (b:bs) = f a' b : outerZipwith f a' b' [] bs
outerZipwith f a' b' (a:as) [] = f a b' : outerZipwith f a' b' as []
outerZipwith f a' b' (a:as) (b:bs) = f a b : outerZipwith f a' b' as bs

或者可能

outerZipwith' :: (a -> b -> c) -> Maybe a -> Maybe b -> [a] -> [b] -> [c]
outerZipwith' _ _ _ [] [] = []
outerZipwith' _ nothing _ [] _ = []
outerZipwith' _ _ nothing _ [] = []
outerZipwith' f a' b' [] (b:bs) = f (fromJust a') b : outerZipwith f a' b' [] bs
outerZipwith' f a' b' (a:as) [] = f a (fromJust b') : outerZipwith f a' b' as []
outerZipwith' f a' b' (a:as) (b:bs) = f a b : outerZipwith f a' b' as bs

所以我能做到

outerZipwith (+) 0 0 [1..5] [10..20]  == [11,19,16,18,20]
outerZipwith (+) 0 0 [1..11] [10..14] == [11,6,7,8,9,10,11]

我发现自己经常需要它,而且我宁愿使用一个常用的习惯用法来使我的代码更易于编写(并且更易于维护),而不是实现outerZipwith,或者如果长度为<长度bs然后zipwith f(重复a)bs else zipwith f as(bs repeat b).

解决方法

这似乎很尴尬,因为你试图跳到最后而不是处理原始操作.

首先,zipwith在概念上是一个zip后跟map(uncurry($)).这是一个重要的观点,因为(un)currying是为什么zipwith是可能的.给定类型[a]和[b]的列表,要应用函数(a – > b – > c)并获得[c]类型的东西,您显然需要每个输入中的一个.执行此操作的两种方法恰好是列表的两个applicative实例,而zipwith是其中一个的liftA2. (另一个例子是标准的,它给出了笛卡尔积 – 如果你愿意的话,是交叉连接).

你想要的语义与任何明显的applicative实例都不对应,这就是为什么它要困难得多.首先考虑一个outerZip :: [a] – > [b] – > [?? a b]它将具有什么类型.结果列表的元素可以分别是a,b或两者.这不仅与任何标准数据类型不对应,因此您不能用它们表达任何有用的因素(A B A * B).

这样的数据类型有它自己的用途,这就是为什么我有my own package defining one.我记得有一个关于hackage(我认为辅助功能比我的少),但我不记得它叫什么.

坚持只是标准的东西,你最终需要一个合理的“认值”,大致转化为拥有一个Monoid实例并使用标识值来填充列表.但是,使用newtype包装器等转换为适当的Monoid和从适当的Monoid转换可能不会比当前实现更简单.

另外,您对列表索引作为键的评论实际上可以进一步发展;任何具有类似密钥概念的Functor与Reader monad是同构的,a.k.a.是从键到值的显式函数. Edward Kmett一如既往地编写了一堆编码这些抽象概念的软件包,在本例中是从the representable-functors package开始构建的.如果你不介意写十几个实例只是为了开始至少……

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐