我很无聊一天,想锻炼我的大脑,所以我决定做99个Haskell的问题 ,但限制自己的自由点式做他们。 这似乎是突然出现的时候,我做的事情的自由点,款式很多的一个问题是:如何申请多个功能相同的值,同时保持各自的结果作为一个独立的实体? 使用尖锐的表示法:
foobar x = [id x, reverse x]
而且我想出迄今无点符号:
foobar' = `map` [id, reverse] ($ x)
我似乎无法得到那个x
掉那里结束。
我很无聊一天,想锻炼我的大脑,所以我决定做99个Haskell的问题 ,但限制自己的自由点式做他们。 这似乎是突然出现的时候,我做的事情的自由点,款式很多的一个问题是:如何申请多个功能相同的值,同时保持各自的结果作为一个独立的实体? 使用尖锐的表示法:
foobar x = [id x, reverse x]
而且我想出迄今无点符号:
foobar' = `map` [id, reverse] ($ x)
我似乎无法得到那个x
掉那里结束。
其他人已经发布了如何使用该做这个Reader
的单子,但是这不是唯一的方法。 事实证明,你的第二个功能是相当接近。 我想你是要发布
foobar' x = (`map` [id, reverse]) ($ x)
由于x
已接近一个最右边的位置,你几乎没有。 首先,改造部分($ x)
到一个函数,因为这是一个有点容易的工作:
-- by the definition of a right operator section
foobar'2 x = (`map` [id, reverse]) (\y -> ($) y x)
接着除去x
通过使一个新的变量进范围,并且将所述函数应用于从拉姆达体x
-- lambda abstraction I think...
foobar'2 x = (`map` [id, reverse]) $ (\z y -> ($) y z) x
改写这个应用程序作为一个功能组成,然后你就可以ETA减少:
-- by definition of '.'
foobar'3 x = (`map` [id, reverse]) . (\z y -> ($) y z) $ x
-- eta reduction
foobar'4 = (`map` [id, reverse]) . (\z y -> ($) y z)
最后,注意我们可以用函数替换拉姆达
-- by definition of `flip`
foobar'5 = (`map` [id,reverse]) . flip ($)
和你有一个免费的点对点形式。
你会感兴趣的Applicative
读者单子的实例:
instance Applicative (e ->)
使用它可以轻松地分发参数:
liftA2 (+) sin cos 3
这里sin
和cos
是函数,其中两个接收的值然后3.个体结果是使用合并(+)
您可以通过进一步结合该Category
的实例(->)
但五言的专业版本(.)
和id
在已定义的Prelude
。
背景: Applicative
例如(e ->)
真表示SKI演算,其中(<*>)
是S组合子和pure
是K个组合子。 S被精确地用于一个参数分配到两个功能:
S f g x = f x (g x)
它需要一个功能应用(FG)和使得无论依赖于x值((FX)(GX))。
使用顺序 :
> let foobar' = sequence [id, reverse]
> foobar' "abcde"
["abcde","edcba"]
有哪些弹出反复,并与各较高的概念和库重新实现,但其本质上是很简单的几个基本的惯用组合程序。 名称可能会有所不同,而在其他方面的一些是可实现:
fork (f,g) x = (f x, g x) -- == (f &&& g)
prod (f,g) x = (f $ fst x, g $ snd x) -- == (f *** g)
pmap f (x,y) = (f x, f y) -- == (f *** f)
dup x = (x,x)
等。当然uncurry f (x,y) == fxy
被使用了许多与这些,太。
&&&
和***
定义在Control.Arrow
,以及first
和second
。 然后prod (f,id) == first f
, prod(id,g) == second g
等等,等等
所以,你的foobar
变
foobar = (\(a,b)->[a,b]) . fork (id,reverse)
= (\(a,b)->[a,b]) . (id &&& reverse)
= (\(a,b)->[a,b]) . (id *** reverse) . dup
= join $ curry ( (\(a,b)->[a,b]) . second reverse)
对于最后一个,您还需要导入Control.Monad
和Control.Monad.Instances
。 又见这个问题 。
后期编辑:此外,使用Control.Applicative
由ertes回答暗示,
= (:) <*> ((:[]) . reverse)