Tri*_*Gao 10 f# ocaml haskell scala typescript
是否存在类似Either的标准和类型,但有3种情况?Haskell有,These
但不是那样.
Tom*_*cek 16
我认为严重依赖这种类型是一种反模式.
使用代数数据类型得到的最好的一点是结果类型会告诉您有关您正在使用的域的信息.对于类似的泛型类型Choice<T1, T2, T3>
,您实际上并没有对域名做任何说明.
我认为option<T>
(aka Maybe
)非常清楚,因为它表示某种类型的值T
存在或由于某种原因而丢失.我认为Either<'T, exn>
仍然很清楚,它说你得到一个价值或一个例外.但是,当您遇到两个以上的案例时,很难理解案例的含义,因此明确定义名称与域匹配的类型可能是个好主意.
(我Choice<T1, T2, T3>
偶尔使用F#,但用法通常仅限于小范围 - 少于50行代码 - 这样我就可以很容易地找到代码消耗它的含义.)
这些被称为联产品实际上Either
只是一个 2 参数联产品。您可以使用 shapeless 库中的 helpers 来构建任意长度的联产品:
type CP = Int :+: String :+: Boolean :+: CNil
val example = Coproduct[CP]("foo")
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用所有有趣的poly
魔法来映射它们或执行其他操作:
object printer extends Poly1 {
implicit def caseInt = at[Int](i => i -> s"$i is an int")
implicit def caseString = at[String](s => s -> s"$s is a string")
implicit def caseBoolean = at[Boolean](b => s -> s"$b is a bool")
}
val mapped = example map printer
mapped.select[(String, String)] shouldEqual "foo is a string"
Run Code Online (Sandbox Code Playgroud)
据我所知,Scala.JS + Shapeless 可以一起工作,所以这可能会给你你想要的。
在最近的Haskell中,我打开了一点厨房水槽.
{-# LANGUAGE PolyKinds, DataKinds, GADTs, KindSignatures,
TypeOperators, PatternSynonyms #-}
Run Code Online (Sandbox Code Playgroud)
然后我将定义类型级列表成员资格
data (:>) :: [x] -> x -> * where
Ze :: (x ': xs) :> x
Su :: xs :> x -> (y ': xs) :> x
Run Code Online (Sandbox Code Playgroud)
现在我拥有了所有有限的总和,而没有找出一大堆OneOfN类型定义:
data Sum :: [*] -> * where
(:-) :: xs :> x -> x -> Sum xs
Run Code Online (Sandbox Code Playgroud)
但是,为了解决Tomas关于可读性的问题,我将使用模式同义词.事实上,这种事情是我多年来一直在讨论模式同义词的原因.
你可以有一个有趣的版本Maybe
:
type MAYBE x = Sum '[(), x]
pattern NOTHING :: MAYBE x
pattern NOTHING = Ze :- ()
pattern JUST :: x -> MAYBE x
pattern JUST x = Su Ze :- x
Run Code Online (Sandbox Code Playgroud)
你甚至可以newtype
用来建立递归总和.
newtype Tm x = Tm (Sum '[x, (Tm x, Tm x), Tm (Maybe x)])
pattern VAR :: x -> Tm x
pattern VAR x = Tm (Ze :- x)
pattern APP :: Tm x -> Tm x -> Tm x
pattern APP f s = Tm (Su Ze :- (f, s))
pattern LAM :: Tm (Maybe x) -> Tm x
pattern LAM b = Tm (Su (Su Ze) :- b)
Run Code Online (Sandbox Code Playgroud)
newtype包装器还允许您对instance
以这种方式构建的类型进行声明.
当然,您也可以使用模式同义词来Either
很好地隐藏迭代.
这种技术并不仅限于总和:你也可以为产品做到这一点,而这正是de Vries和Löh的Generics-SOP库中发生的事情.
这种编码的最大胜利是数据描述本身(类型级别)数据,允许您在deriving
不破坏编译器的情况下烹饪许多样式的功能.
在未来(如果我有我的方式),所有数据类型将被定义,而不是声明,数据类型描述由数据组成,指定数据的代数结构(允许计算通用设备)及其外观(所以你可以看到你在使用特定类型时所做的事情).
但未来已经在这里了.
归档时间: |
|
查看次数: |
706 次 |
最近记录: |