您最有可能写以下哪项?
r = zip xs $ map sqrt xs
或者
r = [(x, sqrt x) | x <- xs]
网上的示例代码似乎表明前者更丰富,是首选方式。
您最有可能写以下哪项?
r = zip xs $ map sqrt xs
或者
r = [(x, sqrt x) | x <- xs]
网上的示例代码似乎表明前者更丰富,是首选方式。
在#haskell 上花费太多时间的人可能会这样写
r = map (id &&& sqrt) xs
(&&&)
是一个有趣的组合器,定义在Control.Arrow
. 它的实际类型签名很复杂,因为它被推广到 Arrow 的所有实例。但它经常与 的(->)
实例一起使用Arrow
,这会导致这种类型签名:
(&&&) :: (a -> b) -> (a -> c) -> a -> (b, c)
虽然我倾向于不经常使用它们,但在这种情况下,我认为我更喜欢列表理解版本,因为它对我来说似乎更干净。
如果你喜欢无点风格,你可能也会喜欢这个:
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 (导入 Control.Applicative):
f = zip <*> map sqrt
我可能会写map
/zip
然后希望我已经写了列表理解。
对于某些类型的问题(尤其是Project Euler),这种特殊情况经常出现,因此我编写了以下小助手:
with :: (a -> b) -> a -> (a,b)
with f a = (a, f a)
这允许您编写示例:
r = map (with sqrt) xs
我可能会写
map (\x -> (x, sqrt x)) xs
如果您更喜欢无点,则以上等效于(在导入Control.Monad
and之后Control.Monad.Instances
)
map (ap (,) sqrt) xs
另一个尚未提及的替代方案是
zipWith (,) xs (map sqrt xs)
我更像是一个“老派”的 Haskellier,所以我会使用zip `ap` map sqrt
并稍后重构它以使用<*>
而不是ap
.
Applicative 是新的 Monad。(从“这些天酷 Haskell 孩子们使用什么?”的意义上说)
我很少使用列表推导,但两者都很花哨。只需使用使您的代码更易于阅读的那个。