I saw several articles on the Internet before, but I didn’t understand them until I looked at the source code of Argo, and found that it also defined these, but with Enum, I understood a lot. If you’re interested, take a look.

Functor, Monad, Applicative refers to a data type, as long as the provisions of the method to realize the type, can be called a Functor/Monad/Applicative.

Functor

Definitions in Haskell:

class Functor f where 
    fmap :: (a -> b) -> f a -> f b 
Copy the code

The type that implements (a->b) -> fa -> f b is called Functor, f is a type that assumes (a->b) is called function, fa is a value in context, as if a were wrapped in Box(a). Context can be represented with such a structure.

/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / / / / take the Box as context * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * struct Box < T > {private var  value: T init(_ value: T) {self.value = value} func unbox() -> T {return self.value}} // Implement (a -> b) -> f a -> f b type called Functor, // ((a->b), Box(a)) -> Box(b) // The first argument (a, b) is a function f, and the second argument is fa. Unbox) // 1.a = unbox a // 2.b = f(a) // 3.Box(b) infix operator <^> {associativity left} func <^><T, U>(f: T -> U, x: Box<T>) -> Box<U> {return x.map(f)} T -> U) -> Box<U> { return Box<U>(f(unbox())) } }Copy the code

Here is a more graphic representation, where (+3) corresponds to our defined function f and Box(2) is the value in context. Take the 2, do the + 3, and then Box.

Functor picture representation

Applicative

Definitions in Haskell:

class (Functor f) => Applicative f where     
    pure :: a -> f a     
    (<*>) :: f (a -> b) -> f a -> f b 
Copy the code

The type that implements f(a -> b) -> F a -> F b, a -> F A, is called Applicative. F (a -> b) refers to the function in context, which can be represented by Box: BoxB> fa value in context, Box(a)

// (Box(a->b), Box(a)) -> Box(b) // 1.f = unbox function // 2.a = unbox a // 3. Call f(a) returns b, b=f(a) // 4.Box(b) infix operator <*> {associativity left} func <*><T, U>(f: Box<T -> U>, x: Box<T>) -> Box<U> { return x.apply(f) } // a->Box(a) func pure<T>(x: T) -> Box<T> {return Box(x)} // Box is Applicative extension Box {func apply<U>(f: Box<T -> U>) -> Box<U> { let function = f.unbox() return map(function) } }Copy the code

Picture explanation: Function and 2 are in Box, which need to be taken out and then put into Box after operation

Applicative picture

Monad

Definitions in Haskell:

class Monad m where 
    return :: a -> m a  
    (>>=) :: m a -> (a -> m b) -> m b 
    ...
Copy the code

The implementation of the m a -> (a -> m b) -> m b type called Monad m A refers to the context of the value, Box(a) (a -> m b) is a function, non-context. Pass in a, return Box(b)

/ / (Box (a), (a - > Box (b))) - > Box (b) / / said the first parameter is in this context, function (a, MB) input unbox a value, Box(b) = f(a) infix operator >>= {associativity left} func >>=<T, U>(x: Box<T>, f: T -> Box<U>) -> Box<U> {return x.flatmap (f)} T -> Box<U>) -> Box<U> { let value = unbox() return f(value) } }Copy the code

Monad image representation

The test code

// Functor Test
let box1 = Box<Int>(2)

// add 2
let function1: (Int -> String) = { x in
    return String(x + 2)
}

let r1 = function1 <^> box1
print(r1.unbox())

// Monad Test
let box2 = Box<Int>(3)
let function2: (Int -> Box<Int>) = { x in
    return Box<Int>((x + 2))
}

let r2 = box2 >>= function2
print(r2.unbox())

// Applicative Test
let box3 = Box<Int>(4)
let function3: Box<Int -> Int> = Box<Int -> Int>({ x in
    return x + 2
})

let r3 = function3 <*> box3
print(r3.unbox())
Copy the code