【发布时间】:2017-04-17 19:04:59
【问题描述】:
我在一篇 Scala 文章中发现了一个非常有趣的示例,我想知道如何在 Haskell 中对其进行编码。
trait Status
trait Open extends Status
trait Closed extends Status
trait Door[S <: Status]
object Door {
def apply[S <: Status] = new Door[S] {}
def open[S <: Closed](d: Door[S]) = Door[Open]
def close[S <: Open](d: Door[S]) = Door[Closed]
}
val closedDoor = Door[Closed]
val openDoor = Door.open(closedDoor)
val closedAgainDoor = Door.close(openDoor)
//val closedClosedDoor = Door.close(closedDoor) // fails to compile
//val openOpenDoor = Door.open(openDoor) // fails to compile
此示例在类型级别编码,您只能打开已关闭的 Door,并且只能关闭打开的 Door。我的第一次尝试只是使用简单的数据类型,但没有按预期工作:
data Status = Open | Closed deriving (Show)
data Door = Door Status deriving (Show)
open :: Door -> Door
open (Door Closed) = Door Open
close :: Door -> Door
close (Door Open) = Door Closed
main = do
let closedDoor = (Door Closed)
let openDoor = open closedDoor
let closedAgainDoor = close openDoor
let closeClosedDoor = close closedDoor
let openOpenedDoor = open openDoor
print closedAgainDoor
这实际上可以编译(除非我尝试打印 closeClosedDoor 或 openOpenedDoor,然后抱怨打开函数中的非详尽模式,这很明显)
所以我想弄清楚我们的类型家族的 GADT 是否可以完成这项任务,但我还不知道怎么做。
有什么想法吗?
【问题讨论】:
标签: scala haskell types functional-programming