LoginSignup
0
0

fp-tsの動画の内容の文字化 - 1

Last updated at Posted at 2024-04-20

fp-tsのtutorial動画があるが
中身を文字で見たかったが それを公開しているところがなかったので書いてみようと思った
※あまりにも長くなったので分割

動画

Chapter 1: pipe and flow

pipe - [A -> B]

\displaylines{
pipe(A, f) \\
\\
A \xrightarrow{f} B
}
import { describe, it } from 'vitest'
import { pipe } from 'fp-ts/lib/function'

describe('fp-ts Tutorial ', () => {
  it('pipe - A -> B', () => {
    const size = (s: string) => s.length

    console.log(pipe('hello', size))

    console.log(size('hello'))
  })
})

実行結果

5
5

pipe - [A -> B -> C]

\displaylines{
pipe(A, f, g) \\
\\
A \xrightarrow{f} B \xrightarrow{g} C
}
import { describe, it } from 'vitest'
import { pipe } from 'fp-ts/lib/function'

describe('fp-ts Tutorial ', () => {
  it('pipe - A -> B -> C', () => {
    const size = (s: string) => s.length
    const isAtLeast3 = (n: number) => n >= 3

    console.log(pipe('hello', size, isAtLeast3))
    console.log(size('hello'))
    console.log(isAtLeast3(size('hello')))
  })
})

実行結果

true
5
true

pipe - [A -> B -> C -> D]

\displaylines{
pipe(A, f, g, h) \\
\\
A \xrightarrow{f} B \xrightarrow{g} C \xrightarrow{h} D
}
import { describe, it } from 'vitest'
import { pipe } from 'fp-ts/lib/function'

describe('fp-ts Tutorial ', () => {
  it('pipe - A -> B -> C -> D', () => {
    const trim = (s: string) => s.trim()
    const size = (s: string) => s.length
    const isAtLeast3 = (n: number) => n >= 3

    const value = ' hello '

    console.log(pipe(value, trim, size, isAtLeast3))
    console.log(value)
    console.log(trim(value))
    console.log(size(trim(value)))
    console.log(isAtLeast3(size(trim(value))))
  })
})

実行結果

true
 hello 
hello
5
true

flow - [A -> B -> C -> D]

\displaylines{
flow(f, g, h) \\
\\
A \xrightarrow{f} B \xrightarrow{g} C \xrightarrow{h} D
}
import { describe, it } from 'vitest'
import { flow } from 'fp-ts/lib/function'

describe('fp-ts Tutorial ', () => {
  it('flow - A -> B -> C -> D', () => {
    const trim = (s: string) => s.trim()
    const size = (s: string) => s.length
    const isAtLeast3 = (n: number) => n >= 3

    const isValid = flow(trim, size, isAtLeast3)

    const value = ' hello '

    console.log(isValid(value))
    console.log(value)
    console.log(trim(value))
    console.log(size(trim(value)))
    console.log(isAtLeast3(size(trim(value))))
  })
})

実行結果

true
 hello 
hello
5
true

Chapter 2: Option

Option<number>

inverse(x) = \left\{
\begin{array}{ll}
None & (x = 0) \\
\frac{1}{x} & (x \neq 0)
\end{array}
\right.
import { describe, it } from 'vitest'
import * as O from 'fp-ts/Option'

describe('fp-ts Tutorial', () => {
  it('Option', () => {
    const inverse = (x: number): O.Option<number> => (x === 0 ? O.none : O.some(1 / x))

    console.log(inverse(0))
    console.log(inverse(2))
  })
})

実行結果

{ _tag: 'None' }
{ _tag: 'Some', value: 0.5 }

従来の書き方

x=0の場合は未定義(エラーが出る)

\displaylines{
inverse(x) = \frac{1}{x}  \\
(x \neq 0)
}
import { describe, it } from 'vitest'

describe('fp-ts Tutorial', () => {
  it('Option', () => {
    const inverse = (x: number): number => {
      if (x === 0) {
        throw Error('Cannot get inverse of 0.')
      }

      return 1 / x
    }

    console.log(inverse(2))
    console.log(inverse(0))
  })
})

実行結果

0.5

実行時にエラーが出る
※'Cannot get inverse of 0.'

O.fold(onNone, onSome)

\displaylines{

inverse(x) = \left\{
\begin{array}{ll}
None & (x = 0) \\
\frac{1}{x} & (x \neq 0)
\end{array}
\right. 

\\

getUiMessageWithInverse(x) = \left\{
\begin{array}{ll}
Cannot \hspace{5pt} get \hspace{5pt} the \hspace{5pt} inverse \hspace{5pt} of \hspace{5pt} \check{x} . & (x = 0) \\
The \hspace{5pt} inverse \hspace{5pt} of \hspace{5pt} \check{x} \hspace{5pt} is \hspace{5pt} \check{inverse(x)}. & (x \neq 0)
\end{array}
\right. 

}
import { describe, it } from 'vitest'
import * as O from 'fp-ts/Option'
import { pipe } from 'fp-ts/lib/function'

describe('fp-ts Tutorial', () => {
  it('Option - O.fold(onNone, onSome)', () => {
    const inverse = (x: number): O.Option<number> => (x === 0 ? O.none : O.some(1 / x))
    const getUiMessageWithInverse = (x: number): string =>
      pipe(
        x,
        inverse,
        O.fold(
          () => `Cannot get the inverse of ${x}.`,
          (ix) => `The inverse of ${x} is ${ix}.`
        )
      )
    console.log(getUiMessageWithInverse(0))
    console.log(getUiMessageWithInverse(2))
  })
})

実行結果

Cannot get the inverse of 0.
The inverse of 2 is 0.5.

Option<number> - safe

safeInverse(x) = \left\{
\begin{array}{ll}
0 & (x = 0) \\
\frac{1}{x} & (x \neq 0)
\end{array}
\right.
import { describe, it } from 'vitest'
import * as O from 'fp-ts/Option'
import { identity, pipe } from 'fp-ts/lib/function'

describe('fp-ts Tutorial', () => {
  it('Option<number> - safe', () => {
    const inverse = (x: number): O.Option<number> => (x === 0 ? O.none : O.some(1 / x))
    const safeInverse = (x: number): number =>
      pipe(
        x,
        inverse,
        O.fold(() => 0, identity)
      )
    console.log(safeInverse(0))
    console.log(safeInverse(2))
  })
})

実行結果

0
0.5

Option<number> - safe - O.getOrElse(onNone)

safeInverse(x) = \left\{
\begin{array}{ll}
0 & (x = 0) \\
\frac{1}{x} & (x \neq 0)
\end{array}
\right.
import { describe, it } from 'vitest'
import * as O from 'fp-ts/Option'
import { pipe } from 'fp-ts/lib/function'

describe('fp-ts Tutorial', () => {
  it('Option<number> - safe - O.getOrElse(onNone)', () => {
    const inverse = (x: number): O.Option<number> => (x === 0 ? O.none : O.some(1 / x))
    const safeInverse = (x: number): number =>
      pipe(
        x,
        inverse,
        O.getOrElse(() => 0)
      )
    console.log(safeInverse(0))
    console.log(safeInverse(2))
  })
})

実行結果

0
0.5

型変更によるエラー

safeInverse(x) = \left\{
\begin{array}{ll}
invalid & (x = 0) \\
\frac{1}{x} & (x \neq 0)
\end{array}
\right.

赤い背景のところでエラーが出る

import { describe, it } from 'vitest'
import * as O from 'fp-ts/Option'
import { pipe } from 'fp-ts/lib/function'

describe('fp-ts Tutorial', () => {
  it('Option<number> - safe - O.getOrElse(onNone)', () => {
    const inverse = (x: number): O.Option<number> => (x === 0 ? O.none : O.some(1 / x))
    const safeInverse = (x: number) =>
      pipe(
        x,
-        inverse,
        O.getOrElse(() => 'invalid')
      )
    console.log(safeInverse(0))
    console.log(safeInverse(2))
  })
})

実行結果

invalid
0.5

※VSCodeなどでエラー表示されるが、実行は可能
※Argument of type '(x: number) => O.Option' is not assignable to parameter of type '(a: number) => Option'.

Option<number> - safe - O.getOrElseW(onNone)

safeInverse(x) = \left\{
\begin{array}{ll}
invalid & (x = 0) \\
\frac{1}{x} & (x \neq 0)
\end{array}
\right.
import { describe, it } from 'vitest'
import * as O from 'fp-ts/Option'
import { pipe } from 'fp-ts/lib/function'

describe('fp-ts Tutorial', () => {
  it('Option<number> - safe - O.getOrElse(onNone)', () => {
    const inverse = (x: number): O.Option<number> => (x === 0 ? O.none : O.some(1 / x))
    const safeInverse = (x: number) =>
      pipe(
        x,
        inverse,
        O.getOrElseW(() => 'invalid')
      )
    console.log(safeInverse(0))
    console.log(safeInverse(2))
  })
})

実行結果

invalid
0.5

※getOrElseW だとエラー表示なし

O.fromNullable(nullableValue)

import { describe, it } from 'vitest'
import * as O from 'fp-ts/Option'

describe('fp-ts Tutorial', () => {
  it('O.fromNullable(nullableValue)', () => {
    const value1 = 3
    const value2 = null
    const value3 = undefined

    console.log(O.fromNullable(value1))
    console.log(O.fromNullable(value2))
    console.log(O.fromNullable(value3))
  })
})

実行結果

{ _tag: 'Some', value: 3 }
{ _tag: 'None' }
{ _tag: 'None' }

Chapter 2.1: Option map, flatten, chain

配列の先頭取得


import { describe, it } from 'vitest'
import * as O from 'fp-ts/Option'

describe('fp-ts Tutorial', () => {
  it('Option - head', () => {
    const head = <A>(as: ReadonlyArray<A>): O.Option<A> =>
      as.length === 0 ? O.none : O.some(as[0])

    console.log(head([5, 6, 7]))
    console.log(head([]))
  })
})

実行結果

{ _tag: 'Some', value: 5 }
{ _tag: 'None' }

O.map(f)


import { describe, it } from 'vitest'
import * as O from 'fp-ts/Option'
import { pipe } from 'fp-ts/lib/function'

describe('fp-ts Tutorial', () => {
  it('O.map(f)', () => {
    const head = <A>(as: ReadonlyArray<A>): O.Option<A> =>
      as.length === 0 ? O.none : O.some(as[0])
    const toUpperCase = (s: string) => s.toUpperCase()
    const addPrefix = (prefix: string) => (s: string) => prefix + s

    const debug_log = <T>(x: T) => {
      console.log(x)
      return x
    }

    const getBestMovie1 = (titles: ReadonlyArray<string>): O.Option<string> =>
      pipe(
        titles,
        debug_log,
        head,
        debug_log,
        O.map((s) => s.toUpperCase()),
        debug_log,
        O.map((s) => `Best - ${s}`)
      )
    const getBestMovie2 = (titles: ReadonlyArray<string>): O.Option<string> =>
      pipe(
        titles,
        debug_log,
        head,
        debug_log,
        O.map(toUpperCase),
        debug_log,
        O.map(addPrefix('Best - '))
      )

    console.log(getBestMovie1(['An American in Rome', 'Winter Holidays']))
    console.log('---------------')
    console.log(getBestMovie1([]))
    console.log('---------------')

    console.log(getBestMovie2(['An American in Rome', 'Winter Holidays']))
    console.log('---------------')
    console.log(getBestMovie2([]))
    console.log('---------------')
  })
})

実行結果

[ 'An American in Rome', 'Winter Holidays' ]
{ _tag: 'Some', value: 'An American in Rome' }
{ _tag: 'Some', value: 'AN AMERICAN IN ROME' }
{ _tag: 'Some', value: 'Best - AN AMERICAN IN ROME' }
---------------
[]
{ _tag: 'None' }
{ _tag: 'None' }
{ _tag: 'None' }
---------------
[ 'An American in Rome', 'Winter Holidays' ]
{ _tag: 'Some', value: 'An American in Rome' }
{ _tag: 'Some', value: 'AN AMERICAN IN ROME' }
{ _tag: 'Some', value: 'Best - AN AMERICAN IN ROME' }
---------------
[]
{ _tag: 'None' }
{ _tag: 'None' }
{ _tag: 'None' }
---------------

従来のやり方


import { describe, it } from 'vitest'

describe('fp-ts Tutorial', () => {
  it('O.map(f)', () => {
    const getBestMovie = (titles: ReadonlyArray<string>): string => {
      const firstTitle = titles[0]

      if (firstTitle === undefined) {
        throw Error('Cannot get the best movie.')
      }

      return `Best 0 ${firstTitle.toLocaleUpperCase()}`
    }

    console.log(getBestMovie(['An American in Rome', 'Winter Holidays']))
    console.log(getBestMovie([]))
  })
})

実行結果

Best 0 AN AMERICAN IN ROME

実行時にエラーが出る
※'Cannot get the best movie.'

O.map(f) - O.some(O.none)


import { describe, it } from 'vitest'
import * as O from 'fp-ts/Option'
import { pipe } from 'fp-ts/lib/function'

describe('fp-ts Tutorial', () => {
  it('O.map(f) - O.some(O.none)', () => {
    const head = <A>(as: ReadonlyArray<A>): O.Option<A> =>
      as.length === 0 ? O.none : O.some(as[0])
    const inverse = (x: number): O.Option<number> => (x === 0 ? O.none : O.some(1 / x))

    const debug_log = <T>(x: T) => {
      console.log(x)
      return x
    }
    const inverseHead = (ns: ReadonlyArray<number>) =>
      pipe(ns, debug_log, head, debug_log, O.map(inverse))

    console.log(inverseHead([0, 2, 4]))
    console.log('------------')
    console.log(inverseHead([]))
    console.log('------------')
  })
})

実行結果

[ 0, 2, 4 ]
{ _tag: 'Some', value: 0 }
{ _tag: 'Some', value: { _tag: 'None' } }
------------
[]
{ _tag: 'None' }
{ _tag: 'None' }
------------

O.map(f) - O.flatten



import { describe, it } from 'vitest'
import * as O from 'fp-ts/Option'
import { pipe } from 'fp-ts/lib/function'

describe('fp-ts Tutorial', () => {
  it('O.map(f) - O.flatten', () => {
    const head = <A>(as: ReadonlyArray<A>): O.Option<A> =>
      as.length === 0 ? O.none : O.some(as[0])
    const inverse = (x: number): O.Option<number> => (x === 0 ? O.none : O.some(1 / x))

    const debug_log = <T>(x: T) => {
      console.log(x)
      return x
    }
    const inverseHead = (ns: ReadonlyArray<number>) =>
      pipe(ns, debug_log, head, debug_log, O.map(inverse), debug_log, O.flatten)

    console.log(inverseHead([0, 2, 4]))
    console.log('------------')
    console.log(inverseHead([2, 4, 6]))
    console.log('------------')
    console.log(inverseHead([]))
    console.log('------------')
  })
})

実行結果

[ 0, 2, 4 ]
{ _tag: 'Some', value: 0 }
{ _tag: 'Some', value: { _tag: 'None' } }
{ _tag: 'None' }
------------
[ 2, 4, 6 ]
{ _tag: 'Some', value: 2 }
{ _tag: 'Some', value: { _tag: 'Some', value: 0.5 } }
{ _tag: 'Some', value: 0.5 }
------------
[]
{ _tag: 'None' }
{ _tag: 'None' }
{ _tag: 'None' }
------------

O.chain(f)



import { describe, it } from 'vitest'
import * as O from 'fp-ts/Option'
import { pipe } from 'fp-ts/lib/function'

describe('fp-ts Tutorial', () => {
  it('O.chain(f)', () => {
    const head = <A>(as: ReadonlyArray<A>): O.Option<A> =>
      as.length === 0 ? O.none : O.some(as[0])
    const inverse = (x: number): O.Option<number> => (x === 0 ? O.none : O.some(1 / x))

    const debug_log = <T>(x: T) => {
      console.log(x)
      return x
    }
    const inverseHead = (ns: ReadonlyArray<number>) =>
      pipe(ns, debug_log, head, debug_log, O.chain(inverse))

    console.log(inverseHead([0, 2, 4]))
    console.log('------------')
    console.log(inverseHead([2, 4, 6]))
    console.log('------------')
    console.log(inverseHead([]))
    console.log('------------')
  })
})

実行結果

[ 0, 2, 4 ]
{ _tag: 'Some', value: 0 }
{ _tag: 'None' }
------------
[ 2, 4, 6 ]
{ _tag: 'Some', value: 2 }
{ _tag: 'Some', value: 0.5 }
------------
[]
{ _tag: 'None' }
{ _tag: 'None' }
------------

Chapter 2.2: Option fromPredicate

O.fromPredicate(predicate) - 1

isEven(x) = \left\{
\begin{array}{ll}
true & (x\bmod 2 = 0) \\
false & (x\bmod 2 \neq 0)
\end{array}
\right.

import { describe, it } from 'vitest'
import * as O from 'fp-ts/Option'

describe('fp-ts Tutorial', () => {
  it('O.fromPredicate(predicate) - 1', () => {
    const isEven = (a: number) => a % 2 === 0
    const getEven = O.fromPredicate(isEven)

    console.log(getEven(4))
    console.log(getEven(5))
  })
})

実行結果

{ _tag: 'Some', value: 4 }
{ _tag: 'None' }

O.fromPredicate(predicate) - 2

isDiscountValid(x) = \left\{
\begin{array}{ll}
true & (x.expired \neq true) \\
false & (x.expired = true)
\end{array}
\right.

import { describe, it } from 'vitest'
import * as O from 'fp-ts/Option'
import { pipe } from 'fp-ts/lib/function'

describe('fp-ts Tutorial', () => {
  it('O.fromPredicate(predicate) - 2', () => {
    type Discount = Readonly<{
      percentage: number
      expired: boolean
    }>

    const isDiscountValid = (discount: Discount) => !discount.expired

    const debug_log = <T>(x: T) => {
      console.log(x)
      return x
    }

    const getDiscountText = (discount: Discount): O.Option<string> =>
      pipe(
        discount,
        debug_log,
        O.fromPredicate(isDiscountValid),
        debug_log,
        O.map(({ percentage }) => `${percentage}% DISCOUNT!`)
      )

    console.log(getDiscountText({ percentage: 10, expired: false }))
    console.log('---------------')
    console.log(getDiscountText({ percentage: 20, expired: true }))
    console.log('---------------')
  })
})

実行結果

{ percentage: 10, expired: false }
{ _tag: 'Some', value: { percentage: 10, expired: false } }
{ _tag: 'Some', value: '10% DISCOUNT!' }
---------------
{ percentage: 20, expired: true }
{ _tag: 'None' }
{ _tag: 'None' }
---------------

O.fromPredicate(refinement)

isCircle(x) = \left\{
\begin{array}{ll}
true & (x.type = Circle) \\
false & (x.type \neq Circle)
\end{array}
\right.

import { describe, it } from 'vitest'
import * as O from 'fp-ts/Option'

describe('fp-ts Tutorial', () => {
  it('O.fromPredicate(refinement)', () => {
    interface Circle {
      type: 'Circle'
      radius: number
    }
    interface Square {
      type: 'Square'
      side: number
    }
    type Shape = Circle | Square

    const isCircle = (s: Shape): s is Circle => s.type === 'Circle'

    const getCircle = O.fromPredicate(isCircle)

    console.log(getCircle({ type: 'Circle', radius: 3 }))
    console.log(getCircle({ type: 'Square', side: 4 }))
  })
})

実行結果

{ _tag: 'Some', value: { type: 'Circle', radius: 3 } }
{ _tag: 'None' }

Chapter 2.3: Option error handling

getMovieAwardHighlight



import { describe, it } from 'vitest'
import * as O from 'fp-ts/Option'
import { pipe } from 'fp-ts/lib/function'

describe('fp-ts Tutorial', () => {
  it('O.alt(f)', () => {
    interface Movie {
      title: string
      releaseYear: number
      ratingPosition: number
      award?: string
    }

    const debug_log = <T>(x: T) => {
      console.log(x)
      return x
    }

    const getMovieAwardHighlight = (movie: Movie): O.Option<string> =>
      pipe(
        movie.award,
        debug_log,
        O.fromNullable,
        debug_log,
        O.map((award) => `Awarded with: ${award}`)
      )

    const movie1: Movie = {
      title: 'The Kingdom of Monads',
      releaseYear: 2023,
      ratingPosition: 1,
      award: 'Oscar'
    }
    const movie2: Movie = {
      title: 'Natural Transformations',
      releaseYear: 2023,
      ratingPosition: 3
    }
    const movie3: Movie = {
      title: 'Fun with for loops',
      releaseYear: 2023,
      ratingPosition: 74
    }

    console.log(getMovieAwardHighlight(movie1))
    console.log('---------------')
    console.log(getMovieAwardHighlight(movie2))
    console.log('---------------')
    console.log(getMovieAwardHighlight(movie3))
    console.log('---------------')
  })
})

実行結果

Oscar
{ _tag: 'Some', value: 'Oscar' }
{ _tag: 'Some', value: 'Awarded with: Oscar' }
---------------
undefined
{ _tag: 'None' }
{ _tag: 'None' }
---------------
undefined
{ _tag: 'None' }
{ _tag: 'None' }
---------------

getMovieTop10Highlight



import { describe, it } from 'vitest'
import * as O from 'fp-ts/Option'
import { pipe } from 'fp-ts/lib/function'

describe('fp-ts Tutorial', () => {
  it('O.alt(f)', () => {
    interface Movie {
      title: string
      releaseYear: number
      ratingPosition: number
      award?: string
    }

    const debug_log = <T>(x: T) => {
      console.log(x)
      return x
    }

    const getMovieTop10Highlight = (movie: Movie): O.Option<string> =>
      pipe(
        movie,
        debug_log,
        O.fromPredicate(({ ratingPosition }) => ratingPosition <= 10),
        debug_log,
        O.map(({ ratingPosition }) => `In TOP 10 at position: ${ratingPosition}`)
      )

    const movie1: Movie = {
      title: 'The Kingdom of Monads',
      releaseYear: 2023,
      ratingPosition: 1,
      award: 'Oscar'
    }
    const movie2: Movie = {
      title: 'Natural Transformations',
      releaseYear: 2023,
      ratingPosition: 3
    }
    const movie3: Movie = {
      title: 'Fun with for loops',
      releaseYear: 2023,
      ratingPosition: 74
    }

    console.log(getMovieTop10Highlight(movie1))
    console.log('---------------')
    console.log(getMovieTop10Highlight(movie2))
    console.log('---------------')
    console.log(getMovieTop10Highlight(movie3))
    console.log('---------------')
  })
})

実行結果

{
  title: 'The Kingdom of Monads',
  releaseYear: 2023,
  ratingPosition: 1,
  award: 'Oscar'
}
{
  _tag: 'Some',
  value: {
    title: 'The Kingdom of Monads',
    releaseYear: 2023,
    ratingPosition: 1,
    award: 'Oscar'
  }
}
{ _tag: 'Some', value: 'In TOP 10 at position: 1' }
---------------
{
  title: 'Natural Transformations',
  releaseYear: 2023,
  ratingPosition: 3
}
{
  _tag: 'Some',
  value: {
    title: 'Natural Transformations',
    releaseYear: 2023,
    ratingPosition: 3
  }
}
{ _tag: 'Some', value: 'In TOP 10 at position: 3' }
---------------
{ title: 'Fun with for loops', releaseYear: 2023, ratingPosition: 74 }
{ _tag: 'None' }
{ _tag: 'None' }
---------------

O.alt(f)



import { describe, it } from 'vitest'
import * as O from 'fp-ts/Option'
import { pipe } from 'fp-ts/lib/function'

describe('fp-ts Tutorial', () => {
  it('O.alt(f)', () => {
    interface Movie {
      title: string
      releaseYear: number
      ratingPosition: number
      award?: string
    }

    const debug_log = <T>(x: T) => {
      console.log(x)
      return x
    }

    const getMovieAwardHighlight = (movie: Movie): O.Option<string> =>
      pipe(
        movie.award,
        // debug_log,
        O.fromNullable,
        // debug_log,
        O.map((award) => `Awarded with: ${award}`)
      )
    const getMovieTop10Highlight = (movie: Movie): O.Option<string> =>
      pipe(
        movie,
        // debug_log,
        O.fromPredicate(({ ratingPosition }) => ratingPosition <= 10),
        // debug_log,
        O.map(({ ratingPosition }) => `In TOP 10 at position: ${ratingPosition}`)
      )

    const getMovieHighlight = (movie: Movie): string =>
      pipe(
        movie,
        debug_log,
        getMovieAwardHighlight,
        debug_log,
        O.alt(() => getMovieTop10Highlight(movie)),
        debug_log,
        O.getOrElse(() => `Released in ${movie.releaseYear}`)
      )

    const movie1: Movie = {
      title: 'The Kingdom of Monads',
      releaseYear: 2023,
      ratingPosition: 1,
      award: 'Oscar'
    }
    const movie2: Movie = {
      title: 'Natural Transformations',
      releaseYear: 2023,
      ratingPosition: 3
    }
    const movie3: Movie = {
      title: 'Fun with for loops',
      releaseYear: 2023,
      ratingPosition: 74
    }

    console.log(getMovieHighlight(movie1))
    console.log('---------------')
    console.log(getMovieHighlight(movie2))
    console.log('---------------')
    console.log(getMovieHighlight(movie3))
    console.log('---------------')
  })
})

実行結果

{
  title: 'The Kingdom of Monads',
  releaseYear: 2023,
  ratingPosition: 1,
  award: 'Oscar'
}
{ _tag: 'Some', value: 'Awarded with: Oscar' }
{ _tag: 'Some', value: 'Awarded with: Oscar' }
Awarded with: Oscar
---------------
{
  title: 'Natural Transformations',
  releaseYear: 2023,
  ratingPosition: 3
}
{ _tag: 'None' }
{ _tag: 'Some', value: 'In TOP 10 at position: 3' }
In TOP 10 at position: 3
---------------

O.altW(f) - W means Widen

赤い背景のところでエラーが出る

import { describe, it } from 'vitest'
import * as O from 'fp-ts/Option'
import { pipe } from 'fp-ts/lib/function'

describe('fp-ts Tutorial', () => {
  it('O.altW(f)', () => {
    const f = (a: O.Option<number>) =>
      pipe(
-        a,
        O.alt(() => O.some('invalid'))
      )

    console.log(f(O.of(3)))
    console.log(f(O.none))
  })
})

実行結果

{ _tag: 'Some', value: 3 }
{ _tag: 'Some', value: 'invalid' }

※VSCodeなどでエラー表示されるが、実行は可能
※Argument of type 'Option' is not assignable to parameter of type 'Option'.

O.altW ならエラー表示なし

import { describe, it } from 'vitest'
import * as O from 'fp-ts/Option'
import { pipe } from 'fp-ts/lib/function'

describe('fp-ts Tutorial', () => {
  it('O.altW(f)', () => {
    const f = (a: O.Option<number>) =>
      pipe(
        a,
        O.altW(() => O.some('invalid'))
      )

    console.log(f(O.of(3)))
    console.log(f(O.none))
  })
})

実行結果

{ _tag: 'Some', value: 3 }
{ _tag: 'Some', value: 'invalid' }
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0