GADT的类似仆人的实现

时间:2018-08-16 11:04:16

标签: haskell gadt servant

我正在阅读出色的Why is servant a type-level DSL?。我已经到了这一节,到目前为止,实现所存在的问题是Endpoint中捕获的数量可以变化,并且如果没有依赖类型,就无法实现全部的链接生成功能。

Endpoint的定义是:

data Method = Get | Post

data Endpoint = Static String Endpoint
              | Capture Endpoint
              | Verb Method

和示例定义为:

getHello :: Endpoint
getHello = Static "hello" (Capture (Verb Get))

twoCaptures :: Endpoint
twoCaptures = Capture (Capture (Verb Post))

noCaptures :: Endpoint
noCaptures = Static "hello" (Verb Post)

非总计链接制作功能是:

linkTo :: Endpoint -> [String] -> Link
linkTo (Static str rest) captureValues  = str : linkTo rest captureValues
linkTo (Capture rest)    (c : cs)       = c   : linkTo rest cs
linkTo (Capture rest)    []             = error "linkTo: capture value needed but the list is empty" -- :-(
linkTo (Verb method)     _              = []

我对以下内容感兴趣:

  

幸运的是,GADT在这里可以提供帮助。我们可以将Endpoint变成GADT   跟踪捕获,然后使用一些类型级别的计算来获取   我们的捕获列表中的链接建立函数的类型,例如   以及通过类型类实例定义链接制作功能   这将通过捕获并为每个添加一个参数   它们...基于GADT的方法在非常稳定的域中也可以很好地工作(除了更易于使用),由于我们所要求的灵活性,因此此处不予考虑。

我对尝试使用GADT方法感兴趣,但是我可以对如何创建GADT做一些提示,该方法将“跟踪捕获,然后使用一些类型级别的计算来获取链接的类型-捕获列表中的功能”

任何人都可以给我一些有关如何开始使用GADT版本的提示。谢谢。

1 个答案:

答案 0 :(得分:2)

我对Servant不熟悉,但也许引述是指某些GADT,例如以下内容。想法是定义一种类型Endpoint t,其中t的格式为String -> String -> ... -> Link,其中所有字符串参数都对应于捕获。完成此操作后,toLink的类型就简单为Endpoint t -> t

我没有使用类型类。

{-# LANGUAGE GADTs #-}
module ServantEndpoint where

type Link = [String]

data Method = Get | Post

data Endpoint t where
   Static :: String -> Endpoint t -> Endpoint t
   Capture :: Endpoint t -> Endpoint (String -> t)
   Verb :: Method -> Endpoint Link

linkTo :: Endpoint t -> t
linkTo e = go e []
   where
   go :: Endpoint t -> Link -> t
   go (Static str rest) l = go rest (str : l)
   go (Capture rest)    l = \s -> go rest (s : l)
   go (Verb _method)    l = reverse l

一个小例子:

test :: Link
test = f "capture1" "capture2"
   where f = linkTo (Capture (Static "static1" (Capture (Static "static2" (Verb Get)))))
-- output: ["capture1","static1","capture2","static2"]