给出函数 fmap :: (a->b) -> IO a -> IO b 的定义
其效果是通过将函数应用于其结果来转换交互。您应该使用 do 构造来定义它。
我应该如何定义 fmap?我对此一无所知?
有人可以帮我吗?
谢谢~!
它看起来像家庭作业或其他东西,所以我会给你足够的提示,这样你就可以自己处理其余的细节。
fmap1 :: (a -> b) -> IO a -> IO b
fmap1 f action =
actionis 作为IO动作,f是来自ato的函数b,因此是 type a -> b。
如果您熟悉>>=具有类型的 monadic bind(简化为IOmonad)
(>>=) :: IO a -> (a -> IO b) -> IO b
现在如果你看
action >>= f
这意味着执行IO返回输出(例如outtype a)并将输出传递给ftype 的操作a -> IO b,因此f out是 type IO b。
如果您查看第二个调用return的具有类型的函数(再次简化为IOmonad)
return :: a -> IO a
它接受 type 的纯值a并给出 type 的IO动作IO a。
现在让我们回顾一下fmap。
fmap1 f action
它执行IO动作,然后f在动作的输出上运行,然后将输出转换为另一个IO类型的动作IO b。所以
fmap1 f action = action >>= g
where
g out = return (f out)
现在是do符号的语法糖。这只是以另一种方式编写绑定>>=。
在do符号中,您可以通过以下方式获得操作的输出
out <- action
所以 bind 只是减少到
action >>= f = do
out <- action
f out
我认为现在您将能够将 fmap 的定义转换为 do 构造。
你熟悉地图吗?
地图的类型是
地图 :: (a -> b) -> [a] -> [b]
如果你跑
地图 (*5) [1,2,3]
你得到
[5,10,15]
map 的重点是给它一个转换函数和一个源列表,并让它将转换应用于列表以获得结果列表。
map 是列表的 fmap。他们希望您为 IO 类型编写 fmap,这有帮助吗?
如果您想了解更多关于 fmap 的信息,请阅读http://learnyouahaskell.com/making-our-own-types-and-typeclasses#the-functor-typeclass
请注意,每个 monad 已经是一个仿函数。但是,如果你想重新实现fmap,你可以很容易地用一元函数来做到这一点。一个单子定律是这样的:
fmap f xs = xs >>= return . f
如果你对 do notation 的理解足够,你应该可以自己翻译。如果没有,请问。