我有時會發現自己需要創建一個函數,將不同的函數映射到兩個值,然後將它們組合在一起。如何做到這一點,而不使用lambda?對haskell中的每個參數應用函數
我的職責是:
f :: a -> b
g :: c -> d
combine :: b -> d -> e
的問題是:如何編寫\x y -> combine (f x) (g y)
不使用拉姆達?
我有時會發現自己需要創建一個函數,將不同的函數映射到兩個值,然後將它們組合在一起。如何做到這一點,而不使用lambda?對haskell中的每個參數應用函數
我的職責是:
f :: a -> b
g :: c -> d
combine :: b -> d -> e
的問題是:如何編寫\x y -> combine (f x) (g y)
不使用拉姆達?
一種替代pointfree拼寫包括通過使用curry
,uncurry
,要麼(***)
(從Control.Arrow
)或bimap
處理參數爲一對(從Data.Bifunctor
):
GHCi> :t \combine f g -> curry (uncurry combine . (f *** g))
\combine f g -> curry (uncurry combine . (f *** g))
:: (a1 -> b1 -> c) -> (a -> a1) -> (b -> b1) -> a -> b -> c
注意的是,不同於jpath的建議,這ISN比非免費版本更短。
如果f = g
您可以使用on
在Data.Function
。否則在base
中沒有該組合器。搜索適當類型的堆棧顯示biSp
從concatenative
。
biSp :: (a -> c) -> (b -> d) -> (c -> d -> e) -> a -> b -> e
但是,如果這是你會從包中使用的唯一功能,你可能不希望依賴於只爲一個包。
除此之外,您可以使用至少略短一些的下列內容,但不會更具可讀性。
(. g) . combine . f
或者在Data.Profunctor
使用dimap
從profunctors
。雖然這也需要另外的套餐,但您可能已經間接依賴profunctors
,因爲您使用的是lens
或某些套餐取決於lens
。
dimap f (. g) combine
這可以很容易地擴展到三個參數。以下所有內容都是相同的,並且從最短到最具結構的順序排列,最後兩個順序很容易將它們擴展到任意數量的參數。
dimap f (dimap g (. h)) combine3
(dimap f . dimap g) (. h) combine3
(dimap f . dimap g . dimap h) id combine3
如果你想知道這個dimap
做什麼。這是一個很好的教程:I love profunctors. They're so easy.
或者只是寫你自己的biSp
。