Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save lagenorhynque/dcc0246cc875f0f6b12f8c7fe85053d2 to your computer and use it in GitHub Desktop.

Select an option

Save lagenorhynque/dcc0246cc875f0f6b12f8c7fe85053d2 to your computer and use it in GitHub Desktop.
KotlinとHaskellでのFunctor, Applicative, Monad, Traversable (相当)の実装
λ> data Box a = Box a deriving (Show, Eq)
type Box :: * -> *
data Box a = ...
-- Functorの実装
λ> :{
λ| instance Functor Box where
λ| fmap f (Box x) = Box $ f x
λ| :}
-- Applicativeの実装
λ> :{
λ| instance Applicative Box where
λ| pure = Box
λ| (Box f) <*> x = fmap f x
λ| :}
-- 利用例
λ> fmap (* 3) (Box 2)
Box 6
it :: Num b => Box b
λ> (*) <$> Box 2 <*> Box 3
Box 6
it :: Num b => Box b
-- Monadの実装
λ> :{
λ| instance Monad Box where
λ| (Box x) >>= f = f x
λ| :}
-- 利用例
λ> Box 2 >>= (\x -> return $ x * 3)
Box 6
it :: Num b => Box b
λ> :{
λ| do
λ| x <- Box 2
λ| return $ x * 3
λ| :}
Box 6
it :: Num b => Box b
-- 利用例
λ> traverse (Box . (* 3)) [1, 2, 3]
Box [3,6,9]
it :: Num b => Box [b]
λ> sequenceA [Box 1, Box 2, Box 3]
Box [1,2,3]
it :: Num a => Box [a]
>>> data class Box<out A>(val value: A)
// Functorのメソッド fmap 相当
>>> fun <A, B> Box<A>.map(f: (A) -> B): Box<B> = Box(f(this.value))
// Applicativeのメソッド <*> 相当
>>> fun <A, B> Box<(A) -> B>.ap(x: Box<A>): Box<B> = x.map { this.value(it) }
// 利用例
>>> Box(2).map { it * 3 }
res3: Line_0.Box<kotlin.Int> = Box(value=6)
>>> Box(2).map { n: Int -> { m: Int -> n * m } }.ap(Box(3))
res4: Line_0.Box<kotlin.Int> = Box(value=6)
// Monadのメソッド >>= 相当
>>> fun <A, B> Box<A>.flatMap(f: (A) -> Box<B>): Box<B> = f(this.value)
// 利用例
>>> Box(2).flatMap { Box(it * 3) }
res6: Line_0.Box<kotlin.Int> = Box(value=6)
// Traversableのメソッド traverse 相当
>>> fun <A, B> List<A>.traverse(f: (A) -> Box<B>): Box<List<B>> = Box(this.map { f(it).value })
// 利用例
>>> listOf(1, 2, 3).traverse { Box(it * 3) }
res8: Line_0.Box<kotlin.collections.List<kotlin.Int>> = Box(value=[3, 6, 9])
// sequence(A)相当
>>> fun <A> List<Box<A>>.sequence(): Box<List<A>> = this.traverse { it }
// 利用例
>>> listOf(Box(1), Box(2), Box(3)).sequence()
res10: Line_0.Box<kotlin.collections.List<kotlin.Int>> = Box(value=[1, 2, 3])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment