我如何将 Either 推广到更多(和递归)类型?
How can I generalize Either to more (and recursive) types?
Scala 的 Either[A, B]
类型是 A
或 B
的类型。
是否有一个概括可以让我定义如下内容?
type JSON = Either[String, Int, Float, List[JSON], Map[String, JSON]]
典型的方法是使用具有最终子类型的密封特征。
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
feature overview of Shapeless 说
shapeless has a Coproduct type, a generalization of Scala's Either
to an arbitrary number of choices.
所以我的第一个想法是尝试这个...
type JSON = String :+: Int :+: Float :+: List[JSON] :+: Map[String, JSON]
... 但不幸的是,对 JSON
的循环引用不起作用。而且我认为这是您尝试使用任何方法都会 运行 遇到的问题。
David Barri 建议一种涉及 "cake pattern" 的方法,但我认为它在这里没有帮助。
即使您定义了自己的 FiveWay
类型(一个需要五个类型参数的“Either
”),Scala 也不允许您定义
type Json = FiveWay[String, Int, Float, List[Json], Map[String, Json]]
为什么?因为类型别名(Json
,此处)不能出现在其自身定义的右侧。
以下示例说明了这一事实:
scala> type Json = Either[String, Json]
<console>:11: error: illegal cyclic reference involving type Json
type Json = Either[String, Json]
更准确地说,Scala 规范 (section 4.3) 告诉我们
the type T
in a type alias type t[tps] = T
may not refer directly or indirectly to the name 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
Scala 的 Either[A, B]
类型是 A
或 B
的类型。
是否有一个概括可以让我定义如下内容?
type JSON = Either[String, Int, Float, List[JSON], Map[String, JSON]]
典型的方法是使用具有最终子类型的密封特征。
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
feature overview of Shapeless 说
shapeless has a Coproduct type, a generalization of Scala's
Either
to an arbitrary number of choices.
所以我的第一个想法是尝试这个...
type JSON = String :+: Int :+: Float :+: List[JSON] :+: Map[String, JSON]
... 但不幸的是,对 JSON
的循环引用不起作用。而且我认为这是您尝试使用任何方法都会 运行 遇到的问题。
David Barri 建议一种涉及 "cake pattern" 的方法,但我认为它在这里没有帮助。
即使您定义了自己的 FiveWay
类型(一个需要五个类型参数的“Either
”),Scala 也不允许您定义
type Json = FiveWay[String, Int, Float, List[Json], Map[String, Json]]
为什么?因为类型别名(Json
,此处)不能出现在其自身定义的右侧。
以下示例说明了这一事实:
scala> type Json = Either[String, Json]
<console>:11: error: illegal cyclic reference involving type Json
type Json = Either[String, Json]
更准确地说,Scala 规范 (section 4.3) 告诉我们
the type
T
in a type aliastype t[tps] = T
may not refer directly or indirectly to the namet
您在这里要做的是应用代数数据类型模式:
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