haskell:函数作为 functor、applicative、monad 和 monoid
在 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 = 6fmap (\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 的两个构建 mempty
和 mappend
,其中 mempty
是 id
函数,任何函数跟 id
函数组合起来,等于其自身。mappend
则是 compose
,组合两个函数,通常用 .
函数来表示。
f.id = fid.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
以上是 haskell:函数作为 functor、applicative、monad 和 monoid 的全部内容, 来源链接: utcz.com/z/264573.html