アドホックな多相性でレスポンスを返す

# **アジェンダ**
* いつものコードについて
* 多相性（ポリモーフィズム ）ってなんでしたっけ
* 結局実現したかったこと

# **はじめに**
普段何気なく書いているコードでもなんとなく理解した気になっていて使っていないかなと…

例えば、以下のような開発中の記録メディアのコード

```.scala
trait Base extends RequestHandler[APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent] {
  protected val contractService: ContractService
  protected val authService: AuthService
  protected val globalSettingService: GlobalSettingService

  override protected def handleRequest(input: APIGatewayProxyRequestEvent, context: Context): APIGatewayProxyResponseEvent = {
    import GlobalSettingConverter._
    import jp.lanscopean.recordingmedia.presentation.core.RequestConverter._
    import jp.lanscopean.recordingmedia.presentation.core.ResponseConverter.ApiResponse

    (for {
      principal     <- input.getPrincipal
      groupId       <- input.getGroupId
      _             <- contractService.authorize(principal.companyId)
      _             <- authService.authorize(principal.companyId, principal.personId, groupId)
      globalSetting <- globalSettingService.getParentSetting(principal.companyId, groupId)
    } yield globalSetting).toResponse ← ★【このtoResponse】
  }
}
```

この**toResponse**の関数の実装をみてみます。

```.scala
implicit class ApiResponse[T](response: Either[AnError, T])(implicit encoder: Encoder[T]) {
  def toResponse: APIGatewayProxyResponseEvent =
    response.fold(
      error => errorResponse(error),
      {
        case ()    => baseResponse.withStatusCode(HttpStatusCode.NoContent)
        case value => baseResponse.withStatusCode(HttpStatusCode.OK).withBody(value.asJson.noSpaces)
      }
    )
}
```

同じファイルに、同じ名前の**toResponse**関数が他にも定義されています。

```.scala
  implicit class ApiOptionalResponse[T](response: Either[AnError, Option[T]])(implicit encoder: Encoder[T]) {
    def toResponse: APIGatewayProxyResponseEvent =
      response.fold(
        error => errorResponse(error),
        {
          case None        => baseResponse.withStatusCode(HttpStatusCode.NoContent)
          case Some(value) => baseResponse.withStatusCode(HttpStatusCode.OK).withBody(value.asJson.noSpaces)
        }
      )
  }

  implicit class ConsumerResponse[T](response: Either[AnError, T]) {
    def toResponse(input: Any): T =
      response.fold(
        {
          case error: LambdaSkipNoError[T] =>
            logger.info(s"Task skipped. input: $input. message: ${error.getMessage} stackTrace: ${error.printStackTrace()}")
            error.response
          case error: LambdaSkipError[T] =>
            logger.error(s"Task skipped. input: $input. message: ${error.getMessage} stackTrace: ${error.printStackTrace()}", error)
            error.response
          case error =>
            logger.error(s"input: $input. message: ${error.getMessage} stackTrace: ${error.printStackTrace()}", error)
            throw error
        },
        identity
      )
  }
```

これは**既存のEither型**にScalaの機能である**拡張メソッド**を利用して
いい感じにAPIの結果を 200: OKとか400: BadRequestとか変換してくれるものですが

これって**多相性（ポリモーフィズム ）**とか呼ばれてるものじゃないのかなぁと

それを調べてみた内容になります。


# **多相性（ポリモーフィズム ）ってなんでしたっけ**
Wikipedia先生から引用
>ポリモーフィズム（英: Polymorphism）とは、プログラミング言語の型システムの性質を表すもので、プログラミング言語の各要素（定数、変数、式、オブジェクト、関数、メソッドなど）についてそれらが複数の型に属することを許すという性質を指す。ポリモルフィズム、多態性、多相性、多様性とも呼ばれる。対義語はモノモーフィズム (Monomorphism)、単態性、単相性で、プログラミング言語の各要素が唯一つの型に属するという性質を指す。

:neutral_face: muzui

## **ポリモーフィズムの種類**
Wikipedia先生から引用
ポリモーフィズムは次のようないくつかの種類に分けられます。

具体的に

### **★アドホック多相**
>関数や演算子の多重定義のように、同じ名前で型の異なる引数に適用できて、その振る舞いは引数の型によって違うような関数の多相性のことをアドホック多相という。

ちなみにad hocとは　「その場しのぎに、特別に」という意味だそうです。

引数の型によって別の実装にディスパッチされるのは、メソッドのオーバーロードがその性質にあたるのかなと思います。

ただ、言語によってどのあたりまで実現できるかは色々よるみたいです。

**いろんなプログラミング言語のアドホック多相**
https://qiita.com/matarillo/items/de65900a37829c48fe71

Scalaで書くとこのような感じになるかなと思います。

```.scala
object Sample {
  def add(x: Int, y: Int): Int = x + y
  def add(x: String, y: String): String = s"$x, $y"
}

Sample.add(1, 2)
Sample.add("Hello", "World")

val res7: Int = 3
val res8: String = Hello, World
```

### **パラメータ多相**
>コードが特定の型を指定せずに書かれることで、さまざまな型に対して透過的に使用できる場合
オブジェクト指向言語ではジェネリクスやジェネリックプログラミングとしても知られる。
関数型言語の分野ではパラメータ多相のことを指して単に多相性と呼ぶ場合がある。

Scalaで言うところの、型パラメータに当たる機能かなと
以下のget関数は Seq[String]や Seq[Int]など異なる型を渡しても動作します。

```.scala
@tailrec
def get[A](list: Seq[A], n: Int): A = {
  list match {
    case _ if list.length < n => throw new RuntimeException("n is over")
    case head :: _ if n == 1 => head
    case head :: Nil => head
    case _ :: tail => get[A](tail, n - 1)
  }
}

get(Seq(1, 2, 3), 2)
get(Seq("a", "b", "c"), 1)
get(Seq("a", "b", "c"), 2)
get(Seq("a", "b", "c"), 3)
get(Seq("a", "b", "c"), 4)


val res3: Int = 2
val res4: String = a
val res5: String = b
val res6: String = c
java.lang.RuntimeException: n is over
```

### **部分型付け**
>部分型多相（subtype polymorphism）や包含多相（inclusion polymorphism）とも。
共通の上位型をもつ複数の型を、1つの名前で扱う場合。
オブジェクト指向言語の分野では部分型付けのことを指して単にポリモーフィズムと呼ぶ場合がある。

Scalaで例を書くとこんな感じかなと思います。

```.scala
trait Animal {
  def call(): String
}
case class Cat() extends Animal {
  def call(): String = "bark"
}
case class Dog() extends Animal {
  def call(): String = "mew"
}
case class Cow() extends Animal {
  def call(): String = "low"
}

Cat().call()
Dog().call()
Cow().call()

val res0: String = bark
val res1: String = mew
val res2: String = low
```

# **結局実現したかったこと**
**toResponse**関数を実装した時に、思っていたこととしては

* お決まりの冗長的なことを書くのを少なくして、コードの見通しをよくしたい
* 異なる型が引数として渡ってきた場合でも最終的に画面に返すレスポンスの形は同じにしたい
* ただ、異なる型で異なる関数名にしてもいいけど、あまり「この型の場合は、別の名前の関数…」実装者に意識させたくない

とか色々考えて実装した結果、アドホックな多相でいつの間にか実現していたのかなぁと思いました。

こういう普段なんとなく使っているものほど、改めて理解しようとすると（型クラスとか色々調べてるとまだまだ理解不足）難しいなぁと。

いかにバグなく、統一した書き方を言語的に縛って、コードの見通しをよくできればなと思います。

# 多相性について調べてみて気になった記事
こういう2分木いまだに理解できてない！
2017年度「プログラミング言語」配布資料 (10) - 京都大学
http://www.fos.kuis.kyoto-u.ac.jp/~igarashi/class/pl/10-polymorphism.html



# 参考文献
[Wikipedia: ポリモーフィズム](https://ja.wikipedia.org/wiki/%E3%83%9D%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%95%E3%82%A3%E3%82%BA%E3%83%A0#:~:text=%E3%83%9D%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%95%E3%82%A3%E3%82%BA%E3%83%A0%EF%BC%88%E8%8B%B1%3A%20Polymorphism%EF%BC%89%E3%81%A8,%E7%9B%B8%E6%80%A7%E3%80%81%E5%A4%9A%E6%A7%98%E6%80%A7%E3%81%A8%E3%82%82%E5%91%BC%E3%81%B0%E3%82%8C%E3%82%8B%E3%80%82)
[Scalaで型クラス入門](https://www.slideshare.net/MakotoFukuhara/scala-56310825) 
[ ]()