如何用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