[英]($) is to (.) as `fmap` is to?
I have a function funcM :: a -> b -> c -> IO (x, y)
我有一个函数funcM :: a -> b -> c -> IO (x, y)
I want to write a function funcM_ :: a-> b-> c-> IO x
so: 我想写一个函数funcM_ :: a-> b-> c-> IO x
所以:
funcM_ = fst `fmap` funcM -- error
I could add back all the points, but it seems like there should be something I could replace fmap
with so that the above will work. 我可以添加所有要点,但似乎应该可以用fmap
替换fmap
某些东西,以便上面的内容起作用。 Kind of like replacing ($) with (.) would make this work in a pure context. 有点像用(。)替换($)会使此工作在纯上下文中进行。
What is the function I am looking for? 我要寻找的功能是什么?
Since you're composing a one-argument function ( fmap
) with a three-argument function ( funcM
), you need three levels of composition: 由于您要使用一个三参数函数( fmap
)来构成一个单参数函数( funcM
),因此需要三个层次的合成:
funcM_ = ((fmap fst .) .) . funcM
This is equivalent to the pointed version by a simple expansion: 通过简单的扩展,它等同于指向版本:
funcM_ x = (fmap fst .) . funcM x
funcM_ x y = fmap fst . funcM x y
funcM_ x y z = fmap fst (funcM x y z)
This follows from the type of fmap
, really: 这实际上来自fmap
的类型:
fmap :: (Functor f) => (a -> b) -> f a -> f b
You're just partially applying the arguments to funcM
so that you have an fa
(here IO (x, y)
) which you give to fmap fst
to get back an fb
( IO x
). 您只是将参数部分地应用于funcM
以便获得一个fa
(在此为IO (x, y)
),将其赋予fmap fst
以返回fb
( IO x
)。
As an aside, M_
usually implies returning m ()
. M_
, M_
通常意味着返回m ()
。
Take a look at the following answer: https://stackoverflow.com/a/20279307/783743 It explains how to convert your code into pointfree style. 请看以下答案: https ://stackoverflow.com/a/20279307/783743它说明了如何将代码转换为无点样式。 Let's start with a non-pointfree definition of funcM_
: 让我们从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
Another way to do this would be to use uncurry
and curry
as follows: 做到这一点的另一种方法是使用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))
Now you can write funcM_
as follows: 现在,您可以编写funcM_
,如下所示:
funcM_ = fmap fst .:: funcM
You could also write .::
in pointfree style as follows: 您还可以按如下所示以无点样式编写.::
:::
(.::) :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
(.::) = (.) . (.) . (.)
Hope that helped. 希望能有所帮助。
Add a dot for each argument to funcM
为funcM
每个参数添加一个点
These are all equivalent: 这些都是等效的:
((fmap fst . ) .) . funcM
((.) . (.) . (.)) (fmap fst) funcM
(fmap . fmap . fmap) (fmap fst) funcM
import Data.Functor.Syntax -- from 'functors' package
(.::) (fmap fst) funcM
Note that all I did was change the implicit ($)
to (.)
. 注意,我所做的只是将隐式($)
更改为(.)
。 :-) :-)
(.)
is the implementation of fmap
for the function instance of Functor
: (.)
是Functor
函数实例的fmap
的实现:
instance Functor ((->) a) b where
fmap f g = f . g
GHCi :t
is your friend. GHCi :t
是您的朋友。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.