如何用fmap表示Haskell中的返回?

时间:2013-11-06 00:07:38

标签: haskell functional-programming

所以我发现fmapFunctor函数可以用Monadic运算符>>=return函数来表示:

fmap' :: (Monad m) => (a -> b) -> m a -> m b
fmap' g x = x >>= (\y ->
                return (g y))

所以我的第一个问题是如何基于fmap实现返回功能?

另外如果我们可以基于fmap实现返回函数,我们可以减少do块中的Haskell表达式吗?这会产生更优雅的代码吗?

例如:

Just x -> do 
    y <- f x
    return (a:y)

2 个答案:

答案 0 :(得分:3)

我们通常无法在return方面实施fmapMonadFunctor更强大。

但是,作为一项练习,我们可以尝试提出这样一个问题:第二项操作(如果有的话)是否可以在return轮流中实施fmap?我们可以通过查看类型来攻击这个问题。 (我们将使用pure类中的Applicative而不是return - 它们基本上是相同的操作。)

fmap :: Functor f => (a -> b) -> f a -> f b
pure :: Applicative f => a -> f a

嗯,这可能是一种可能的方法,如果我们有以下功能:

-- This is like the standard `const` function, but restricted to the `()` type:
const' :: a -> () -> a
const' a = \() -> a

然后我们可以写这个,“几乎是”pure / return

almostThere :: Functor f => a -> f () -> f a
almostThere a = fmap (const' a)

然后,如果我们有以下课程,我们可以用它来写pure

class Functor f => Pointed f where
    unit :: f ()

pure :: Pointed f => a -> f a
pure a = almostThere a unit

简而言之,这归结为returnpureunit都是允许您从头开始制作f的功能,fmap只允许您制作f,如果您已经另一个。您无法使用fmap来实施return / pure,除非您可以访问具有从头开始制作f的“权力”的第三个操作。我展示的unit操作可能是最简单的具有“权力”的操作。

答案 1 :(得分:2)

只有return不可能的仿函数最简单的例子是(,) a

instance Functor ((,) a) where
  fmap f (a, x) = (a, f x)

但要使其成为monad,要实现return,您需要凭空生成a值(适用于任何类型!)。唯一的方法是return x = (undefined, x),这几乎不是解决方案......