简体   繁体   English

($)是(。),就像`fmap`是?

[英]($) 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以返回fbIO 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: 做到这一点的另一种方法是使用uncurrycurry ,如下所示:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM