我有一个函数funcM :: a -> b -> c -> IO (x, y)
我想写一个函数funcM_ :: a-> b-> c-> IO x
所以:
funcM_ = fst `fmap` funcM -- error
我可以添加所有积分,但似乎应该有一些我可以替换fmap
以便以上工作。有点像用(。)替换($)会使它在纯粹的上下文中工作。
我在寻找什么功能?
答案 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
另一种方法是使用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
(.::) = (.) . (.) . (.)
希望有所帮助。
答案 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
是你的朋友。