Skip to content

haskell: function as functor, applicative, monad and monoid #16

Description

@Lucifier129

在 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 的两个构建 mempty 和 mappend,其中 mempty 是 id 函数,任何函数跟 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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions