Haskell 地图/zip 对比。列表理解

问题描述 投票:0回答:7

您最有可能写以下哪一项?

r = zip xs $ map sqrt xs

r = [(x, sqrt x) | x <- xs]

网上的示例代码似乎表明前者更丰富,是首选方式。

haskell zip list-comprehension pointfree combinators
7个回答
27
投票

在 #haskell 上花费太多时间的人可能会写成

r = map (id &&& sqrt) xs

(&&&)
是一个在
Control.Arrow
中定义的有趣组合器。它的实际类型签名很复杂,因为它被推广到 Arrow 的所有实例。但它经常与
(->)
Arrow
实例一起使用,从而产生以下类型签名:

(&&&) :: (a -> b) -> (a -> c) -> a -> (b, c)

18
投票

虽然我不太经常使用它们,但在这种情况下,我想我更喜欢列表理解版本,因为它对我来说似乎更干净。

如果您喜欢无点自由风格,您可能也会喜欢这个:

f = zip `ap` map sqrt

ap
存在于 Control.Monad 中,在这种情况下,它可以被认为是 S 组合器,它概括了 SKI 演算中的应用:

ap f g x == f x (g x)
ap const const == id

正如 Conal 指出的,这也可以从 Monad 推广到 Applicative,从而 (

import Control.Applicative
):

f = zip <*> map sqrt

13
投票

我可能会写

map
/
zip
,然后希望我写了列表理解。


12
投票

我可能会写

map (\x -> (x, sqrt x)) xs

如果您喜欢无积分,以上相当于(导入

Control.Monad
Control.Monad.Instances
后)

map (ap (,) sqrt) xs

另一种尚未提及的替代方案是

zipWith (,) xs (map sqrt xs)

11
投票

对于某些类型的问题(尤其是Project Euler),这种特殊情况经常出现,因此我编写了以下小助手:

with :: (a -> b) -> a -> (a,b)
with f a = (a, f a)

这允许您编写示例:

r = map (with sqrt) xs

8
投票

我更像是一个“老派”Haskellier,所以我会使用

zip `ap` map sqrt
,然后重构它以使用
<*>
而不是
ap

Applicative 是新的 Monad。 (从“Cool Haskell Kids 现在使用什么?”的意义上来说)


7
投票

SO是一场狗屎秀。感谢您的搭车。

© www.soinside.com 2019 - 2024. All rights reserved.