您最有可能写以下哪一项?
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,从而 (
import Control.Applicative
):
f = zip <*> map sqrt
我可能会写
map
/zip
,然后希望我写了列表理解。
我可能会写
map (\x -> (x, sqrt x)) xs
如果您喜欢无积分,以上相当于(导入
Control.Monad
和 Control.Monad.Instances
后)
map (ap (,) sqrt) xs
另一种尚未提及的替代方案是
zipWith (,) xs (map sqrt xs)
对于某些类型的问题(尤其是Project Euler),这种特殊情况经常出现,因此我编写了以下小助手:
with :: (a -> b) -> a -> (a,b)
with f a = (a, f a)
这允许您编写示例:
r = map (with sqrt) xs
我更像是一个“老派”Haskellier,所以我会使用
zip `ap` map sqrt
,然后重构它以使用 <*>
而不是 ap
。
Applicative 是新的 Monad。 (从“Cool Haskell Kids 现在使用什么?”的意义上来说)
SO是一场狗屎秀。感谢您的搭车。