Lucifier129.github.io icon indicating copy to clipboard operation
Lucifier129.github.io copied to clipboard

haskell: function as functor, applicative, monad and monoid

Open Lucifier129 opened this issue 7 years ago • 1 comments

在 haskell 里,function 本身也是 functor, applicative, monad 和 monoid。

理念

function 是天然的 container。

- b 是 test 函数包含的 value, test a 函数调用是获取 container 内部 value 的方式
test :: a -> b

function as functor

将 fmap 应用于 function 这种 functor,fmap f function。相当于构造一个新函数 \a -> f (test a)

test a 把 function 里包含的 value 取出来,作为 f 的参数传入。然后 fmap 需要返回 functor,所以返回包裹的新函数 \a -> f (test a)

验证代码如下

- 输出 (2 + 1) * 2 = 6 
fmap (\x -> x * 2) (\x -> x + 1) $ 2

function as applicative

applicative 的函数 <*> 签名是 (<*>) :: Applicative f => f (a -> b) -> f a -> f b,两个 container 里,一个包含的 value 是 function 类型,另一个包含的是参数,<*> 把两个容器合并起来,将另一个 container 里的参数 value,传入 function 类型的 container 里。

function 自身是容器,其返回值是容器内的 value。那么容器里的 value 又是函数的情况就是高阶函数(返回函数的函数)。

验证代码如下

- 两个函数的第一个参数是同样的,其返回值,一个是函数,一个是参数,调用后 z * 3 的结果,作为参数,传入 y -> x + y 函数
- 相当于构造了函数 \x -> x + (x * 3),输出 12
(\x y -> x + y) <*> (\z -> z * 3) $ 3

function as monad

monad 的 >>= 函数签名是 (>>=) :: Monad m => m a -> (a -> m b) -> m b,第二个参数是一个用上一个容器里的 value 构造下一个容器的函数。

验证代码如下

- 第一个 monad 里的 value 是 x + 1,作为参数传入了 `a -> m b`
- 因为 `a -> m b` 也要返回相同的 monad,所以它是高阶函数,上一个 monad 的 value 填充了其第一个参数,第二个参数跟上一个 monad 的参数是相同的。
- 相当于构造了函数 \x -> (x + 1) * x,输出 6
(\x -> x + 1) >>= (\x y -> x * y) $ 2

function as monoid

function 可以满足 monoid 的两个构建 memptymappend,其中 memptyid 函数,任何函数跟 id 函数组合起来,等于其自身。mappend则是 compose,组合两个函数,通常用 . 函数来表示。

f.id = f
id.f = id
(f.g).h = f.(g.h) 

use do notation for function

既然 function 也是 monad,那么我们就可以使用 do notation 来写。

- 从 n1 是 \x -> x + 1 的返回值
- 我们用 const 构造一个函数 monad,方便 <- 获取值
- 最后用 const 构造新的函数 monad,结束这个过程
- test 2 将输入 (x + 1) + ((x + 1) *2) = 9
test = do
  n1 <- \x -> x + 1
  n2 <- const $ n1 * 2
  const $ n1 + n2

Lucifier129 avatar Aug 05 '18 13:08 Lucifier129

找到一篇更详尽的文章:Haskell functions as functors, applicatives and monads

Lucifier129 avatar Aug 06 '18 02:08 Lucifier129