Scalaの記事で本当に興味深い例が見つかりました。私はHaskellでどのようにエンコードされているのだろうかと思っています。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
を閉じることができるタイプのレベルで符号化します。単純なデータ型を使用していましたが、意図したとおりに動作しません。私の最初の試み:私は、open関数で非網羅的なパターンを訴えたcloseClosedDoor
またはopenOpenedDoor
を印刷しようとしない限り、
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
これは実際にある、(コンパイル明らかに)
GADTのタイプファミリーがこの作業を達成できるかどうかを判断しようとしていますが、まだどのように把握できていません。
アイデア?
あなたは 'DataKinds'答えに私を打つ。最初にコンパイルをチェックせずに投稿したいとは思っていませんでしたが、最初に 'stack setup'を実行しなければなりませんでした。私は 'TypeFamilies'で' toggle'アイデアが好きですが、それについては考えていませんでした。 – bheklilr
ニース、私は自分自身に来て、まだ言語の高度な機能を学んでいるとは思わない。 –
より良い推論のために、 'toggle ::(s〜Toggle t、t〜Toggle s)=> Door s - > Do t 'です。または 'class Toggled s t | s - > t、t - > sはトグル::ドアs - >ドアt'です。あなたはおそらくGHC 8用の注入型のファミリーを使用することができますが、まだそれらを購入しません。 – dfeuer