“If I had a world of my own, everything would be nonsense. Nothing would be what it is, because everything would be what it isn't. And contrary wise, what is, it wouldn't be. And what it wouldn't be, it would. You see?” ― Lewis Carroll, Alice's Adventures in Wonderland & Through the Looking-Glass

### Identity 本身就有 从来没见过有人给这些数据类型按过中文名字, 不然我来, 这样也更好的体会这些数据类型的意图.

``````newtype Identity a = Identity { runIdentity :: a }
``````
``````case class Identity[A](run: A)
``````

``````Identity :: a -> Identity a
runIdentity :: Identity a -> a
``````

``````runIdentity (Identity 1)
``````
```1
```
``````Identity(1).run
``````

``````instance Functor Identity where
fmap f (Identity a) = Identity (f a)

return a = Identity a
Identity a >>= f = f a
``````

``````implicit val identityFunctor: Functor[Identity] = new Functor[Identity] {
def fmap[A, B](f: A => B): Identity[A] => Identity[B] = {
case Identity(a) => Identity(f(a))
}
}

def pure[A](a: A): Id[A] = Identity(a)
def flatMap[A, B](f: A => Identity[B]): Identity[A] => Identity[B] = {
case Identity(a) => f(a)
}
}
``````

Identity 看起来什么也没有干，就跟 identity 函数一样，但是实际上, 它也跟 identity 相对于函数一样 相对于类型非常有用.

### Maybe 可能会有

``````data Maybe a = Just a | Nothing
``````

ADT 在 Scala 可以用 trait 表示, 而且, Scala 中的 `Maybe` 叫做 `Option`:

``````trait Option[+A]
case class Some[A](a: A) extends Option[A]
case object None extends Option[Nothing]
``````

Haskell 中定义一个 ADT 十分简单，不像 Scala 那么啰嗦。左边是类型构造器，右边有数据构造器，你会发现有一根竖线 `|` ， 它分隔着两个构造器

• `Just`
• `Nothing`

``````instance Functor Maybe where
fmap f (Just a) = Just (f a)
fmap f Nothing = Nothing
``````
``````implicit val optionFunctor: Functor[Option] = new Functor[Option] {
def fmap[A, B](f: A => B): Option[A] => Option[B] = {
case Some(a) => Some(f(a))
case None => None
}
}
``````

``````instance Monad Maybe where
return a = Just a
(Just a) >>= f = f a
Nothing >>= f = Nothing
``````
``````implicit val optionMonad: Monad[Option] = new Monad[Option] {
def flatMap[A, B](f: A => Option[B]): Option[A] => Option[B] = {
case Some(a) => f(a)
case None => None
}
}
``````

Maybe 有用在于能合适的处理 偏函数 Partial Function 的返回值。 偏函数相对于 全函数 Total Function 是指只能对部分输入返回输出的函数。

``````[1,2,3] !! 4
``````
``````List(1,2,3).get(4)
``````

### Either 要么有要么有

Either 的定义也很简单

``````data Either a b = Left a | Right b
``````
``````trait Either[+A, +B]
case class Left[+A, +B](a: A) extends Either[A, B]
case class Right[+A, +B](b: B) extends Either[A, B]
``````

#### Product & Coproduct

Tuple 的 `fst` 箭头能让 `(a, b)` 到达 `a` 对象，而箭头 `snd` 能让其到达 `b` 对象。

``````class Endofunctor m => Monad m where
eta :: a -> (m a)
mu :: m m a -> m a
``````

``````class Functor t where
fmap :: (a -> b) -> (t a -> t b)
``````

t a 的 kind 是 *，所以 t 必须是 kind * -> * 也就是说，m 必须是接收一个类型参数的类型构造器

``````instance Monad (Either a) where
Left  l >>= _ = Left l
Right r >>= k = k r
``````

``````newtype Reader e a = Reader { runReader :: (e -> a) }
``````

• e 是输入
• a 是结果
• 构造 Reader 类型需要确定 输入的类型 e 与输出的类型 a
• `runReader` 的类型是 `runReader:: (Reader e a) -> (e -> a)`

``````instance Monad (Reader e) where
return a         = Reader \$ \_ -> a
``````

• f 类型是 `(a -> Reader e a)`
• g 其实就是是 destructure 出来的 runReader，也就是 e -> a
• 所以 (g e) 返回 a
• f (g e) 就是 `Reader e a`
• 再 run 一把最后得到 a

``````import Control.Monad.Reader

data Environment = Env
{ fistName :: String
, lastName :: String
} deriving (Show)

helloworld = do
return "Hello " ++ f ++ l

runHelloworld :: String
runHelloworld = runReader helloworld \$ Env "Jichao" "Ouyang"
``````

#### do notation

• do 中所有 <- 的右边都是 `Reader Environment String` 类型
• do 中的 return 返回类型也必须为 `Reader Environment String`
• `asks firstName` 返回的是 `Reader Environment String` 类型， `<-` 可以理解成吧 monad `Reader Environment` 的内容放到左边的 f, 所以 f 的类型是 String。

``````helloworld = (asks firstName) >>=
\l -> return "Hello " ++ f ++ l
``````

### Writer 光出进没有

``````example :: Writer String String
example  = do
tell "How are you?"
tell "I'm fine thank you, and you?"
return "Hehe Da~"

output :: (String, String)
output = runWriter example
-- ("Hehe Da~", "How are you?I'm fine thank you, and you?")
``````

Writer 的定义更简单

``````newtype Writer l a = Writer { runWriter :: (a,l) }
``````

• w 是 log
• a 是 返回值

``````instance (Monoid w) => Monad (Writer w) where
return a             = Writer (a,mempty)
(Writer (a,l)) >>= f = let (a',l') = runWriter \$ f a in
Writer (a',l `mappend` l')
``````
• return 不会有任何 log，l 是 monoid 的 mempty
• f 的类型为 `a -> Writer l a`
• `runWriter \$ f a` 返回 `(a, l)`

### State 变化会有

``````newtype State s a = State { runState :: s -> (a, s) }
``````

``````instance Monad (State s) where
return a        = State \$ \s -> (a,s)
(State x) >>= f = State \$ \s -> let (v,s') = x s in
runState (f v) s'
``````

return 很简单，就不用解释了。

x 类型是 `s -> (a, s)` ,所以 x s 之后会返回 结果和状态。也就是运行当前 State，把结果 v 传给函数 f，返回的 State 再接着上次状态运行。

``````import Control.Monad.Trans.State.Strict
test :: State Int Int
test = do
a <- get
modify (+1)
b <- get
return (a + b)

main = print \$ show \$ runState test 3
-- (7, 4)
``````

### Validation 检查检查

Validation 没有在标准库中，但是我觉得好有用啊，你可以在 ekmett 的 github 中找到源码

``````data Validation e a = Failure e | Success a
``````

ADT定义看起来跟 Either 是一样的，不同的是 左边Left Failure 是 含幺半群Monoid

#### 含幺半群Monoid

monoid 首先得是 半群Semigroup ，然后再 含幺。

``````class Semigroup a where
(<>) :: a -> a -> a
(<>) = mappend
``````

``````class Monoid a where
mempty  :: a
mappend :: a -> a -> a
``````

``````instance Semigroup [a] where
(<>) = (++)
``````

``````instance Monoid [a] where
mempty  = []
mappend = (++)
``````

Monoid 的 `<>` 满足：

• mempty <> a = a
• a <> b <> c = a <> (b <> c)

#### 回到 Validation

``````instance Semigroup e => Semigroup (Validation e a) where
Failure e1 <> Failure e2 = Failure (e1 <> e2)
Failure _  <> Success a2 = Success a2
Success a1 <> Failure _  = Success a1
Success a1 <> Success _  = Success a1
``````

``````data Info = Info {name: String, phone: String} deriving Show
``````

``````notEmpty :: String -> String -> Validation [String] String
notEmpty desc "" = Failure [desc <> " cannot be empty!"]
notEmpty _ field = Success field
``````

notEmpty 检查字符是否为空，如果是空返回 Failure 包含错误信息，若是非空则返回 Success 包含 field

``````phoneNumberLength :: String -> String -> Validation [String] String
phoneNumberLength desc field | (length field) == 11 = Success field
| otherwise = Failure [desc <> "'s length is not 11"]
``````

``````instance Semigroup e => Applicative (Validation e) where
pure = Success
Failure e1 <*> Failure e2 = Failure e1 <> Failure e2
Failure e1 <*> Success _  = Failure e1
Success _  <*> Failure e2 = Failure e2
Success f <*> Success a = Success (f a)
``````
• 失败应用到失败会 concat 起来
• 失败跟应用或被成功应用还是失败
• 只有成功应用到成功才能成功，这很符合验证的逻辑，一旦验证中发生任何错误，都应该返回失败。
``````createInfo :: String -> String -> Validation [String] Info
createInfo name phone = Info <\$> notEmpty "name" name <*> phoneNumberLength "phone" phone
``````

``````createInfo "jichao" "12345678910" -- Success Info "jichao" "12345678910"
createInfo "" "123" -- Failure ["name cannot be empty!", "phone's length is not 11"]
``````

### Cont 接下来有

``````add :: Int -> Int -> Int
``````

``````addCPS :: Int -> Int -> (Int -> r) -> r
addCPS a b k = k (a + b)
``````

``````newtype Cont r a = Cont { runCont :: ((a -> r) -> r) }
``````

``````add :: Int -> Int -> Cont k Int
add a b = return (a + b)
``````

``````instance Monad (Cont r) where
return a = Cont (\$ a)
m >>= k  = Cont \$ \c -> runCont m \$ \a -> runCont (k a) c
``````

`(\$ a)` 比较有意思, 我们都知道 `f \$ g a` 其实就是 `f(g a)`, 所以 `\$` 其实就是一个 apply 左边的函数到右边表达式的中缀函数, 如果写成前缀则是 `(\$ (g a) f)`. 是反的是因为 `\$` 是有结合, 需要右边表达式先求值, 所以只给一个 a 就相当于 `(\$ a) = \f -> f a`

1

2

3

4

5