Haskell应用成语?

oro*_*ome 8 haskell idioms

我是Haskell的新手,并且对如何以最惯用和最清晰的方式表达一些操作感到困惑.目前(还会有更多)我很困惑<*>(我甚至不确定该怎么称呼).

例如,如果我有,比方说

f = (^2)
g = (+10)
Run Code Online (Sandbox Code Playgroud)

作为代表性的功能(实际上它们更复杂,但关键在于它们是不同的和不同的),然后

concatMap ($ [1,2,3,4,10]) [(f <$>), (g <$>) . tail . reverse] 
Run Code Online (Sandbox Code Playgroud)

concat $ [(f <$>), (g <$>) . tail . reverse] <*> [[1,2,3,4,10]]
Run Code Online (Sandbox Code Playgroud)

完成同样的事情.

是其中一个更惯用的Haskell,是否有人暗示Haskell经验丰富的读者,而另一个则不然.也许有更多(更好)的方式来表达完全相同的东西.这两种方法之间是否存在概念上的差异,像我这样的新手Haskeller可能会丢失?

Lee*_*Lee 10

无论你的函数(f <$>),并(g <$>).tail.reverse(在这种情况下列表)返回一个独异类型,这样就可以使用mconcat,将它们转换成一个单一的功能.然后,您可以将此函数直接应用于输入列表,而不是将其包装在另一个列表中并使用concatMap:

mconcat [(f <$>), (g <$>).tail.reverse] $ [1,2,3,4,10]
Run Code Online (Sandbox Code Playgroud)

为了对此进行扩展,函数a -> bMonoidif 的实例b是monoid.在实施mappend这种功能是:

mappend f g x = f x `mappend` g x
Run Code Online (Sandbox Code Playgroud)

或者等价的

mappend f g = \x -> (f x) `mappend` (g x)
Run Code Online (Sandbox Code Playgroud)

所以给定两个函数fg返回一个monoid类型b,fmappend g返回一个函数,该函数将其参数应用于fg并使用Monoid实例组合结果b.

mconcat具有类型Monoid a => [a] -> a并使用输入列表的所有元素组合mappend.

列表是monoids,其中mappend== (++)so

mconcat [(f <$>), (g <$>).tail.reverse]
Run Code Online (Sandbox Code Playgroud)

返回一个类似的函数

\x -> (fmap f x) ++ (((fmap g) . tail . reverse) x)
Run Code Online (Sandbox Code Playgroud)


Sam*_*den 9

就个人而言,我会写

f = (^2)
g = (+10)

let xs = [1,2,3,4,10]
in (map f xs) ++ (map g . tail $ reverse xs)
Run Code Online (Sandbox Code Playgroud)

在一个非常应用型"心情",我将取代后的部分in

((++) <$> map f <*> map g . tail . reverse) xs
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我实际上并不认为它更具可读性.如果您不直接了解它的含义,请花一些时间来理解()的Applicative实例.((->) a)Reader

我认为这个选择实际上取决于你想要做什么,即你的输出意味着什么.在您的示例中,任务是非常抽象的(基本上只是展示了Applicative可以做什么),因此使用哪个版本并不明显.

直观的Applicative实例[]与组合有关,所以我会在这样的情况下使用它:

-- I want all pair combinations of 1 to 5
(,) <$> [1..5] <*> [1..5]
Run Code Online (Sandbox Code Playgroud)

如果你有很多函数,并且你想要尝试使用多个参数的这些函数的所有组合,我确实会使用.的[]实例Applicative.但是,如果你所追求的是不同变换的串联,我会这样写(我在上面做过).

仅仅是我2美分作为中等体验的Haskeller.