Haskell地图/邮编Vs. 列表理解

qre*_*est 19 zip haskell list-comprehension combinators pointfree

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

r = zip xs $ map sqrt xs
Run Code Online (Sandbox Code Playgroud)

要么

r = [(x, sqrt x) | x <- xs]
Run Code Online (Sandbox Code Playgroud)

互联网上的示例代码似乎表明前者更为丰富且是首选方式.

Car*_*arl 25

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

r = map (id &&& sqrt) xs
Run Code Online (Sandbox Code Playgroud)

(&&&)是一个有趣的组合器Control.Arrow.它的实际类型签名很复杂,因为它推广到Arrow的所有实例.但它经常与(->)实例一起使用Arrow,这导致了这种类型的签名:

(&&&) :: (a -> b) -> (a -> c) -> a -> (b, c)
Run Code Online (Sandbox Code Playgroud)

  • Dan,我认为这可能是最容易在实际代码中使用的Arrow组合器.它的名字非常令人回味:你可以大声读出那行代码作为"map id和sqrt to xs". (8认同)
  • 我称之为"不透明的haskell".在某一点上它只是难以辨认,这一点因曝光而异. (7认同)

dan*_*lei 16

虽然我不经常使用它们,但在这种情况下,我认为我更喜欢列表理解版本,因为它对我来说似乎更清晰.

如果你是点自由风格,你也可能喜欢这个:

f = zip `ap` map sqrt
Run Code Online (Sandbox Code Playgroud)

ap存在于Control.Monad中,在这种情况下,它可以被认为是S组合子,它在SKI演算中推广应用:

ap f g x == f x (g x)
ap const const == id
Run Code Online (Sandbox Code Playgroud)

正如Conal指出的那样,这也可以从Monad推广到Applicative(导入Control.Applicative):

f = zip <*> map sqrt
Run Code Online (Sandbox Code Playgroud)

  • 或者,简化/概括从`Monad`到`Applicative`,`f = zip <*> map sqrt`.虽然我个人更喜欢`map(id &&& sqrt)xs`和carl的答案. (2认同)

Nor*_*sey 12

我可能会写map/ zip然后希望我写了列表理解.


Mtn*_*ark 10

对于某些类型的问题(特别是Project Euler),这个特殊情况经常出现,我写了下面的小助手:

with :: (a -> b) -> a -> (a,b)
with f a = (a, f a)
Run Code Online (Sandbox Code Playgroud)

这允许您编写示例:

r = map (with sqrt) xs
Run Code Online (Sandbox Code Playgroud)


Gre*_*con 10

我可能会写

map (\x -> (x, sqrt x)) xs
Run Code Online (Sandbox Code Playgroud)

如果你喜欢自由点,上面是等同于(在已进口Control.MonadControl.Monad.Instances)

map (ap (,) sqrt) xs
Run Code Online (Sandbox Code Playgroud)

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

zipWith (,) xs (map sqrt xs)
Run Code Online (Sandbox Code Playgroud)


BMe*_*eph 7

我更像是一个"老派"Haskellier,所以我会使用zip `ap` map sqrt它,然后重构它来<*>代替ap.

适用的是新的Monad.(在"酷Haskell孩子们最近使用的是什么?"的意义上)

  • 箭头是新的monad,不是吗? (3认同)

Tho*_*ing 6

我很少使用列表推导,但两者都很花哨.只需使用使代码更易于阅读的代码.