Monads

From bibbleWiki
Jump to navigation Jump to search

Introduction

Heard about this with a friend and never really revisited it. With my attention at home on Rust, thought I might write something down

The Maybe Monad

Well possibly the Option monad for me. To make one of these you need define something to wrap your thing with and a function which could fail that returns the wrapper type

return :: a => Maybe a
>>= :: Maybe a

This was explained to me a little better with this picture.

What's the Point

  • Same idea works for other effects, e.g. reading from environments, input/output
  • Supports pure programming with effects
  • Use of effects explicit in types
  • Functions that work for any effect

Second Time Through

Really want to get this into my head. It is another Mathy thing that just requires me to have a light bulb moment.

Step 1 - Starting Code

So the YouTube started off with this which I might need to change

function square(x: number): number {
    return x * x;
}

function addOne(x: number): number {
    return x + 1;
}

// Which allows us to chain the two together. e.g.
addOne(square(2)) => 5

// I think this is the goal. To do something extra which uses the input data
// This example confused me because it is not valid typescript
addOne(square(2)) => {
    result: 5,
    logs: [
        "square(2) => 4",
        "addOne(4) => 5"
    ]
}

I think what they were suggest is they want the two functions to return an object with logs e.g.

const result = addOneWithLogs(squareWithLogs(2))
// Where result is
{
    result: 5,
    logs: [
        "square(2) => 4",
        "addOne(4) => 5"
    ]
}

Step 2 - Implement new Funcs

First we define an interface to hold the result we are after. i.e. the result and logs

interface NumberWithLogs {
    result: number;
    logs: string[];
}

Now we make our new addOneWithLogs and squareWithLogs to get our result

function squareWithLogs(x: number): NumberWithLogs {
    const result = x * x;
    return {
        result,
        logs: [`Squared ${x} toget ${result}`]
    };
}

function addOneWithLogs(x: NumberWithLogs): NumberWithLogs {
    return {
        result: x.result + 1,
        logs: x.logs.concat([
            `Added one to ${x.result} to get ${x.result + 1}`
        ])
    };
}

const result2 = addOneWithLogs(squareWithLogs(2));