使用 TypeInType 进行数据族实例的种类提升

Dag*_*Dag 2 haskell

我正在尝试为强类型文件路径创建一个通用的自由类别(路径)和文件系统实例。我希望新的TypeInType扩展能够使这种更通用的路径类型成为可能,在 2013 年的早期工作似乎需要将文件系统部分绑定到类别部分,但我遇到了一个问题,我似乎不这样做即使它被:kindGHCI接受,也可以将数据族实例提升到类型级别。

\n\n

我可能会遗漏一些明显的东西;我已经离开 Haskell 和编程有一段时间了,即使那时我也不是高级类型级编程的专家。

\n\n

我想要在 GHC 8 中实现的目标可能吗?

\n\n

代码

\n\n
{-# LANGUAGE TypeInType, TypeFamilies, GADTs #-}\n\nimport Data.Kind\n\ndata family Vertex g\n\ndata family Edge g (a :: Vertex g) (b :: Vertex g)\n\ndata Path g (a :: Vertex g) (b :: Vertex g) where\n    Nil :: Path g a a\n    Cons :: Edge g a b -> Path g b c -> Path g a c\n\ndata FileSystem\n\ndata instance Vertex FileSystem = Root | Home | Working | Directory | File\n\ndata instance Edge FileSystem where\n    RootDirectory :: Edge FileSystem Root Directory\n    HomeDirectory :: Edge FileSystem Home Directory\n    WorkingDirectory :: Edge FileSystem Working Directory\n    DirectoryName :: String -> Edge FileSystem Directory Directory\n    FileName :: String -> Edge FileSystem Directory File\n    FileExtension :: String -> Edge FileSystem File File\n
Run Code Online (Sandbox Code Playgroud)\n\n

编译错误

\n\n
$ ghc Path.hs \n[1 of 1] Compiling Main             ( Path.hs, Path.o )\n\nPath.hs:18:38: error:\n    \xe2\x80\xa2 Data constructor \xe2\x80\x98Root\xe2\x80\x99 cannot be used here\n        (it comes from a data family instance)\n    \xe2\x80\xa2 In the second argument of \xe2\x80\x98Edge\xe2\x80\x99, namely \xe2\x80\x98Root\xe2\x80\x99\n      In the type \xe2\x80\x98Edge FileSystem Root Directory\xe2\x80\x99\n      In the definition of data constructor \xe2\x80\x98RootDirectory\xe2\x80\x99\n
Run Code Online (Sandbox Code Playgroud)\n\n

GHCI

\n\n

注释掉Edge FileSystem代码编译的声明,我可以在 GHCi 中尝试一些东西。

\n\n
*Main> :set -XTypeInType -XTypeFamilies -XGADTs\n*Main> :k Edge FileSystem \nEdge FileSystem :: Vertex FileSystem -> Vertex FileSystem -> *\n*Main> :k Root\nRoot :: Vertex FileSystem\n*Main> :k Edge FileSystem Root Directory\nEdge FileSystem Root Directory :: *\n
Run Code Online (Sandbox Code Playgroud)\n

Ben*_*son 5

我认为你的解决方案过于复杂了。这些NodeEdge数据系列是导致错误的原因 -数据系列不会升级,即使有TypeInType- 并且它们不会在以下更简单的设计上添加任何内容:

infixr 5 :>
data Path (g :: k -> k -> *) (x :: k) (y :: k) where
    Nil :: Path g x x
    (:>) :: g x y -> Path g y z -> Path g x z
Run Code Online (Sandbox Code Playgroud)

Path g是 s 的类型对齐列表g,使得gs 的类型像多米诺骨牌一样连接起来。或者,将类型视为集合,Path g是有向图的自由范畴中的态射类型,其中节点为k,边为g :: k -> k -> *。或者,将 视为g逻辑关系,Path gg的自反传递闭包。

在本例中,kg分别是以下FileSystemItem类型FileSystemPart

data FileSystemItem = Root | Home | Working | Directory | File
data FileSystemPart (dir :: FileSystemItem) (base :: FileSystemItem) where
    RootDirectory    ::           FileSystemPart Root      Directory
    HomeDirectory    ::           FileSystemPart Home      Directory
    WorkingDirectory ::           FileSystemPart Working   Directory
    DirectoryName    :: String -> FileSystemPart Directory Directory
    FileName         :: String -> FileSystemPart Directory File
    FileExtension    :: String -> FileSystemPart File      File

type FileSystemPath = Path FileSystemPart
Run Code Online (Sandbox Code Playgroud)

FileSystemPaths范畴中的态射集合也是如此FileSystemItem

ghci> :k FileSystemPath
FileSystemPath :: FileSystemItem -> FileSystemItem -> *
Run Code Online (Sandbox Code Playgroud)

例如:

myDocument :: FileSystemPath Home File
myDocument = HomeDirectory :> DirectoryName "documents" :> FileName "foo" :> FileExtension "hs" :> Nil
Run Code Online (Sandbox Code Playgroud)

请注意,您不需要TypeInTypeTypeFamilies重型机械 - 您只需要为文件系统本身PolyKinds定义 kind-polymorphicPathDataKindsplus 。GADTs

  • @Dag我不知道推广“数据”系列本身的复杂性,但我确实知道[依赖Haskell仍然在路线图上](https://typesandkinds.wordpress.com/2016/07/24 /dependent-types-in-haskell-progress-report/),甚至可能在这十年。[Richard Eisenberg 的论文](https://github.com/goldfirere/thesis)(当前预览)指定了 Dependent Haskell 的设计,尽管我无法评论其内容,因为我还没有时间阅读它 (2认同)