如何用fmap表示Haskell中的退货?

如何用fmap表示Haskell中的退货?,haskell,functional-programming,Haskell,Functional Programming,所以我发现fmap,一个函子函数可以用一元运算符>=和返回函数来表示,如下所示: fmap' :: (Monad m) => (a -> b) -> m a -> m b fmap' g x = x >>= (\y -> return (g y)) 因此,我的第一个问题是如何基于fmap实现返回函数 另外,如果我们可以基于fmap实现返回函数,我们可以减少do块中的Haskell表达式吗?这会产生更优雅的代码吗 例如:

所以我发现
fmap
,一个
函子
函数可以用一元运算符
>=
返回
函数来表示,如下所示:

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)
Just x->do

y最简单的函子例子是
返回不可能的
(,)a

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

但要使其成为monad,要实现
return
,您需要凭空生成
a
值(对于任何类型!)。唯一的方法是
返回x=(未定义,x)
,这几乎不是一个解决方案…

我们通常无法在
fmap
方面实现
返回
Monad
Functor
更强大

然而,作为练习,我们可以试着问这样一个问题:第二个操作(如果有的话)是什么,可以在
fmap
中依次实现
return
?我们可以通过查看类型来解决这个问题。(我们将使用
Applicative
类中的
pure
,而不是
return
——它们基本上是相同的操作。)

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

-- This is like the standard `const` function, but restricted to the `()` type:
const' :: a -> () -> a
const' a = \() -> a
然后我们可以写这个,它“几乎”是纯的
/
返回

almostThere :: Functor f => a -> f () -> f a
almostThere a = fmap (const' a)
然后如果我们有下面的类,我们可以用它来编写

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

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

长话短说,这归结起来就是
return
pure
unit
都是允许您从头开始创建
f
的函数,而
fmap
仅允许您在已有另一个函数的情况下创建
f
。您无法使用
fmap
实现
return
/
pure
,除非您可以访问第三个操作,该操作具有从头开始创建
f
的“能力”。我展示的
单元
操作可能是最简单的具有这种“能力”的操作。

…不,这是不可行的。作为单子比作为函子更严格。单子始终可以被视为函子,但反之则为false。函子没有创建包装值的方法-
fmap
只能将包装值转换为另一个包装值。要创建包装的值,您需要一些功能更强大的应用程序,比如有
pure::a->fa
。要回答您的另一个问题:是的,您可以使代码更紧凑
do{y有点相切,但是有一个众所周知的函数
join::Monad m=>m(ma)->MA
join
可以用
>=
id
来编写,
>=
可以用
join
fmap
来编写。您可能有兴趣了解如何编写。但是,这是针对一般a的。当a本身是一个Monoid时,有一个非常好的Monad实例—编写器Monad u在它成为WriterT Identity的同义词之前,sed将作为一个新类型实现。
class Functor f => Pointed f where
    unit :: f ()

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