在Elm中,我如何表达口头函数类型defn:`route:Url.Parser(Route - > a)a`?

时间:2017-04-01 13:57:09

标签: routing elm

我试图从url-parser了解此代码:

route : Url.Parser (Route -> a) a 
route =
    Url.oneOf
        [ Url.map Home top
        , Url.map BlogList (s "blog" <?> stringParam "search")
        , Url.map BlogPost (s "blog" </> int)
        ]

它是:&#34; route是一个函数,它采用1)Parser,2)一个函数,它接受Route并返回a, 3)a&#34;?

这似乎不正确,因为如果只是列出参数,那么它在哪里表示route本身的返回值?

我对榆树很新,但是让我离开的是->包含在parens中,然后在结尾处没有-> route返回的内容。

2 个答案:

答案 0 :(得分:1)

简单的答案是route这里不是一个真正的函数,而是一个常量:它代表一种特殊的Parser

现在,这当然提出了它代表什么样的解析器这个更难的问题?

这是一个相当棘手的问题。我相信在解析器组合器上有一些背景可能对此有帮助(https://en.wikipedia.org/wiki/Parser_combinator)。

但无论如何,它花了我一段时间,我可能仍然会弄错。 这些是我经历的步骤:

  1. 让我们看一下Parser可以做些什么。您可以使用parsePathparseHash执行此操作。每个承诺,如果您提供Parser类型Parser (a->a) a(其中a是通用类型变量),那么它会将Location转换为Maybe a }
  2. 让我们看看你有什么样的解析器原语。例如,stringParser (String -> a) a,而intParser (Int -> a) a
  3. 现在,查看组合器,尤其是</>Parser a b -> Parser b c -> Parser a c。如果您写string </> int,您将获得Parser (String -> Int -> c) c。这是可能的,因为string中的类型变量可以替换为Int -> c,因此它变为Parser (String -> Int -> c) (Int -> c)
  4. 基于3号。我的结论是,Parser a b表示可以解析复杂a的一部分的解析器,以将其简化为更简单的b
  5. 从包装用户的角度来看,这反过来了。如果您使用数据类型Route表示路线,则必须定义Parser (Route -> a) a才能将网址转换为内部代表。如果Route的某个构造函数与MyTwoParamsRoute String Int类似,那么您首先需要使用某些组合器(myTwoParamsParser : Parser (String -> Int -> a) a</>)来定义<?>然后使用map MyTwoParamsRoute myTwoParamsParse实际应用构造函数。
  6. 所以对原始问题的答案很长:route : Parser (Route -> a) a代表一个解析器,它可以解析某个字符串中的Route(通常是url的散列或路径部分) - 同时提供一旦字符串被Route表示的字符串缩小,其余的解析器可以进一步解析余数。

答案 1 :(得分:0)

由于您只在=中的route =之前看到函数名称,这意味着它不需要参数。 您还可以在注释中看到,因为没有->。 括号内有一个。

route因此,返回Url.Parser (Route -> a) a

根据我的理解,它会返回Parser a b类型 其中a是一个函数(Route -> a)b可以是任何内容(此处名为a,但它无关紧要。)

->指的是类型Parser“封装”的函数。 我不知道如何更好地解释它,但看看库函数。他们以类似的方式工作 http://package.elm-lang.org/packages/evancz/url-parser/2.0.1/UrlParser