Site cover image

fhhm’s blog

foldで同じスーパークラスを持つ別のサブクラスを返す

foldではNoneの場合とSomeの場合の両方で同じ型を返すことが期待される。

そのため、下記はtype mismatchとなる。

sealed trait Name

case class OnlyKana(firstName: String, lastName: String) extends Name
case class KanjiAndKana(firstName: String, lastName: String, firstNameKana: String, lastNameKana: String) extends Name

def hasKanjiName(name: String): Boolean = ???
def splitName(name: String): Seq[String] = ???
      
val maybeName: Option[String] = ???
val defaultName = kanjiAndKana("太郎", "山田", "たろう", "やまだ")
val name = maybeName.fold(defaultName) {name =>
  val splited = splitName(name)
  if (hasKanjiName(name)) {
      kanjiAndKana(splited(0), splited(1), splited(2), splited(3))
  } else {
      onlyKana(splited(0), splited(1))
  }
}
// KanjiAndKanaまたはOnlyKanaが返るため、type mismatch

fold[T]でスーパークラスを指定するとエラーが解消できる。

sealed trait Name

case class OnlyKana(firstName: String, lastName: String) extends Name
case class KanjiAndKana(firstName: String, lastName: String, firstNameKana: String, lastNameKana: String) extends Name

def hasKanjiName(name: String): Boolean = ???
def splitName(name: String): Seq[String] = ???
      
val maybeName: Option[String] = ???
val defaultName = kanjiAndKana("太郎", "山田", "たろう", "やまだ")
// foldで[Name]を指定する
val name = maybeName.fold[Name](defaultName) {name =>
  val splited = splitName(name)
  if (hasKanjiName(name)) {
      kanjiAndKana(splited(0), splited(1), splited(2), splited(3))
  } else {
      onlyKana(splited(0), splited(1))
  }
}