($)是(。)as`fmap`是?

时间:2014-01-07 00:47:16

标签: haskell functor pointfree

我有一个函数funcM :: a -> b -> c -> IO (x, y)

我想写一个函数funcM_ :: a-> b-> c-> IO x所以:

funcM_ = fst `fmap` funcM -- error

我可以添加所有积分,但似乎应该有一些我可以替换fmap以便以上工作。有点像用(。)替换($)会使它在纯粹的上下文中工作。

我在寻找什么功能?

3 个答案:

答案 0 :(得分:8)

由于您正在使用三参数函数(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,以便您拥有f a(此处为IO (x, y)),您可以fmap fst取回f b IO x 1}}(M_)。

另外,m ()通常意味着返回{{1}}。

答案 1 :(得分:4)

看一下以下答案:https://stackoverflow.com/a/20279307/783743它解释了如何将代码转换为无点样式。让我们从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

另一种方法是使用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))

现在您可以按如下方式编写funcM_

funcM_ = fmap fst .:: funcM

您还可以按照以下方式编写.::无点样式:

(.::) :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
(.::) = (.) . (.) . (.)

希望有所帮助。

答案 2 :(得分:3)

funcM

的每个参数添加一个点

这些都是等价的:

((fmap fst . ) .) . funcM
((.)  . (.)  . (.))  (fmap fst) funcM
(fmap . fmap . fmap) (fmap fst) funcM

import Data.Functor.Syntax -- from 'functors' package
(.::) (fmap fst) funcM

请注意,我所做的只是将隐式($)更改为(.)。 : - )

(.)fmap的函数实例Functor的实现:

instance Functor ((->) a) b where
  fmap f g = f . g

GHCi :t是你的朋友。