[英]($) is to (.) as `fmap` is to?
我有一個函數funcM :: a -> b -> c -> IO (x, y)
我想寫一個函數funcM_ :: a-> b-> c-> IO x
所以:
funcM_ = fst `fmap` funcM -- error
我可以添加所有要點,但似乎應該可以用fmap
替換fmap
某些東西,以便上面的內容起作用。 有點像用(。)替換($)會使此工作在純上下文中進行。
我要尋找的功能是什么?
由於您要使用一個三參數函數( fmap
)來構成一個單參數函數( funcM
),因此需要三個層次的合成:
funcM_ = ((fmap fst .) .) . funcM
通過簡單的擴展,它等同於指向版本:
funcM_ x = (fmap fst .) . funcM x
funcM_ x y = fmap fst . funcM x y
funcM_ x y z = fmap fst (funcM x y z)
這實際上來自fmap
的類型:
fmap :: (Functor f) => (a -> b) -> f a -> f b
您只是將參數部分地應用於funcM
以便獲得一個fa
(在此為IO (x, y)
),將其賦予fmap fst
以返回fb
( IO x
)。
M_
, M_
通常意味着返回m ()
。
請看以下答案: https ://stackoverflow.com/a/20279307/783743它說明了如何將代碼轉換為無點樣式。 讓我們從funcM_的非pointfree定義funcM_
:
funcM_ a b c = fmap fst (funcM a b c)
-- But `\x -> f (g x)` is `f . g`. Hence:
funcM_ a b = fmap fst . (funcM a b)
-- But `\x -> f (g x)` is `f . g`. Hence:
funcM_ a = (fmap fst .) . (funcM a)
-- But `\x -> f (g x)` is `f . g`. Hence:
funcM_ = ((fmap fst .) .) . funcM
做到這一點的另一種方法是使用uncurry
和curry
,如下所示:
uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d
uncurry3 f (a, b, c) = f a b c
curry3 :: ((a, b, c) -> d) -> a -> b -> c -> d
curry3 f a b c = f (a, b, c)
(.::) :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
f .:: g = curry3 (f . (uncurry3 g))
現在,您可以編寫funcM_
,如下所示:
funcM_ = fmap fst .:: funcM
您還可以按如下所示以無點樣式編寫.::
:::
(.::) :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
(.::) = (.) . (.) . (.)
希望能有所幫助。
為funcM
每個參數添加一個點
這些都是等效的:
((fmap fst . ) .) . funcM
((.) . (.) . (.)) (fmap fst) funcM
(fmap . fmap . fmap) (fmap fst) funcM
import Data.Functor.Syntax -- from 'functors' package
(.::) (fmap fst) funcM
注意,我所做的只是將隱式($)
更改為(.)
。 :-)
(.)
是Functor
函數實例的fmap
的實現:
instance Functor ((->) a) b where
fmap f g = f . g
GHCi :t
是您的朋友。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.