我应该如何阅读这种类型的语法?

How should I read this type syntax?

我正在通读 Type-Driven Development with Idris,我 运行 在尝试使用页面上的 valToString 函数时遇到了一些令人困惑的格式23.具体我加了个函数洞:

valToString : (x : Bool) -> StringOrInt x -> String
valToString x val = (?f val)

当我向 REPL 询问这个洞的类型时,这是打印的结果:

*Hello> :t f
  x : Bool
  val : case x of
          True => Int
          False => String
--------------------------------------
f : case x of   True => Int False => String -> String
Holes: Main.f

val的类型在这里已经足够可读了,但是我应该如何阅读f的类型呢?书中提到 on page 19 空格在 Idris 中很重要;如果我将它用于我的程序中的类型,这是否是有效语法?

看来这与空格无关。只是格式错误。

这个

f : case x of   True => Int False => String -> String

可以这样重新格式化:

f : (case x of {True => Int; False => String}) -> String

当我在 Idris repl 中键入 :t f 时,我会看到接下来的内容:

*Hello> :t f
  x : Bool
  val : StringOrInt x
--------------------------------------
f : StringOrInt x -> String
Holes: Main.f

这种情况只是类型 StringOrInt x 的内联版本。虽然格式很差。可能写这章的时候用的是老版本的Idris

更新(2017 年 7 月 23 日)

不幸的是,不是每个人都有书 :( 我试图猜测 StringOrInt 的类型,但我没有准确地猜到它。我在我的代码中使用了下一个定义:

StringOrInt : Bool -> Type
StringOrInt True  = Int
StringOrInt False = String

根据这个定义,我从上面得到了输出。而实际上 StringOrInt 以下一种方式定义:

StringOrInt : Bool -> Type
StringOrInt x = case x of
    True => Int
    False => String

这两个定义在语义上是等价的。区别仅在于句法。但显然这会导致 :t f 命令的编译器输出不同。

我打开了对应的issue:

https://github.com/idris-lang/Idris-dev/issues/3937