Skip to content

Instantly share code, notes, and snippets.

@lagenorhynque
Last active November 14, 2017 15:00
Show Gist options
  • Select an option

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

Select an option

Save lagenorhynque/4d4bde78743dc54f497ef9fe8be1820d to your computer and use it in GitHub Desktop.
(ns polymorphism
(:require [cats.context :as ctx]
[cats.core :as m]
[cats.protocols :as p]
[cats.util :as util]))
(defn my-map [f coll]
(lazy-seq
(when-let [s (seq coll)]
(cons (f (first s))
(my-map f (rest s))))))
(def number-monoid
(reify
p/Context
p/Semigroup
(-mappend [_ x y]
(+ x y))
p/Monoid
(-mempty [_]
0)))
(def list-monoid
(reify
p/Context
p/Semigroup
(-mappend [_ x y]
(concat x y))
p/Monoid
(-mempty [_]
())))
-- パラメータ多相によるmap
myMap :: (a -> b) -> [a] -> [b]
myMap _ [] = []
myMap f (x:xs) = f x : myMap f xs
-- アドホック多相(by 型クラス)によるmempty, mappend
class MyMonoid a where
myMempty :: a
myMappend :: a -> a -> a
instance MyMonoid Int where
myMempty = 0
myMappend = (+)
instance MyMonoid [a] where
myMempty = []
myMappend = (++)
def myMap[A, B](f: A => B, xs: List[A]): List[B] = xs match {
case Nil => Nil
case y :: ys => f(y) :: myMap(f, ys)
}
trait MyMonoid[A] {
def myMempty: A
def myMappend(x: A, y: A): A
}
implicit def intMonoid: MyMonoid[Int] = new MyMonoid[Int] {
def myMempty = 0
def myMappend(x: Int, y: Int): Int = x + y
}
implicit def listMonoid[A]: MyMonoid[List[A]] = new MyMonoid[List[A]] {
def myMempty = Nil
def myMappend(x: List[A], y: List[A]): List[A] = x ++ y
}
polymorphism=> (defn sum [coll monoid]
#_=> (ctx/with-context monoid
#_=> (reduce m/mappend (m/mempty) coll)))
#'polymorphism/sum
polymorphism=> (sum [] number-monoid)
0
polymorphism=> (sum [1 2 3] number-monoid)
6
polymorphism=> (sum [] list-monoid)
()
polymorphism=> (sum [[1 2] [3]] list-monoid)
(1 2 3)
> :{
| mySum :: MyMonoid a => [a] -> a
| mySum = foldr myMappend myMempty
| :}
> mySum ([] :: [Int])
0
> mySum ([1,2,3] :: [Int])
6
> mySum ([] :: [[Int]])
[]
> mySum ([[1,2], [3]] :: [[Int]])
[1,2,3]
scala> def mySum[A: MyMonoid](xs: List[A]): A = xs.foldLeft(implicitly[MyMonoid[A]].myMempty)(implicitly[MyMonoid[A]].myMappend)
mySum: [A](xs: List[A])(implicit evidence$1: MyMonoid[A])A
scala> mySum(List[Int]())
res24: Int = 0
scala> mySum(List[Int](1,2,3))
res25: Int = 6
scala> mySum(List[List[Int]]())
res26: List[Int] = List()
scala> mySum(List[List[Int]](List(1,2),List(3)))
res27: List[Int] = List(1, 2, 3)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment