如何将更多(和递归)类型推广?

use*_*956 3 scala either type-alias

Scala的Either[A, B]类型是或者是A或者B.

是否有一个概括,让我定义如下的东西?

type JSON = Either[String, Int, Float, List[JSON], Map[String, JSON]]
Run Code Online (Sandbox Code Playgroud)

Chr*_*tin 8

典型的方法是使用具有最终亚型的密封性状.

sealed trait JSON
final case class StringJSON(x: String) extends JSON
final case class IntJSON(x: Int) extends JSON
final case class FloatJSON(x: Float) extends JSON
final case class ListJSON(x: List[JSON]) extends JSON
final case class MapJSON(x: Map[String, JSON]) extends JSON
Run Code Online (Sandbox Code Playgroud)

Shapeless功能概述

shapeless具有Coproduct类型,Scala的概括为Either任意数量的选择.

所以我的第一个想法是尝试这个......

type JSON = String :+: Int :+: Float :+: List[JSON] :+: Map[String, JSON]
Run Code Online (Sandbox Code Playgroud)

...但不幸的是,循环引用JSON不起作用.而且我认为这是你尝试的任何方法都会遇到的问题.


大卫巴里提出了一种涉及"蛋糕模式"的方法,尽管我认为这在这方面没有用.


jub*_*0bs 6

即使您定义了自己的FiveWay类型(" Either"将采用五种类型参数),Scala也不允许您定义

type Json = FiveWay[String, Int, Float, List[Json], Map[String, Json]]
Run Code Online (Sandbox Code Playgroud)

为什么?因为类型别名(Json,此处)不能出现在其自己定义的右侧.以下示例说明了这一事实:

scala> type Json = Either[String, Json]
<console>:11: error: illegal cyclic reference involving type Json
       type Json = Either[String, Json]
Run Code Online (Sandbox Code Playgroud)

更确切地说,Scala规范(第4.3节)告诉我们

类型T在类型别名type t[tps] = T可以不直接或间接参考名t

相反,你想要做的是应用代数数据类型模式:

sealed trait Json

final case class JsonString(string: String) extends Json

final case class JsonInt(int: Int) extends Json

final case class JsonFloat(float: Float) extends Json

final case class JsonArray(list: List[Json]) extends Json

final case class JsonObject(map: Map[String, Json]) extends Json
Run Code Online (Sandbox Code Playgroud)