给 Haskell 用家的 Idris 入坑指南

  1. 没有 Cabal 或者 Stack 这样的包管理器,也没有 Idris Platform 之类的东西,到官网下二进制包解压完就可以了。
  2. 然而,Idris 确实有「包描述文件」ipkg。安装网上的包的话,你需要把包下载下来,然后运行 idris --install xxx.ipkg。
  3. 你几乎不需要开扩展——因为自带的功能已经够多了……扩展几乎是只牵涉到 ER 元编程、DSL Notation 等少数几个高级特性。
  4. Idris 默认是严格求值的,不过可以用 Lazy 类型实现惰性求值。这个类型是特殊实现的,会自动加上隐式转换。
  5. Idris 和 Haskell 里面 ::: 的用法正好相反。: 用于声明,:: 用于数组连接。表达式中的「卡类型」不用 (x : t) 而是用 the 函数:the t x
  6. Idris 的顶层函数必须写类型声明,而且和 C/C++ 一样,必须先声明再使用。相互递归的话用 mutual 块。
  7. 对 data,构造器和类型名字不能相同。Edwin 的惯例是用 Mk 前缀,我习惯用 New 前缀。
  8. String 是个原始类型,不是 List Char。可以使用 unpack 函数将 String 转换为 List Char,用 pack 转换回来。
  9. [] 去围类型来代表 List 的语法糖是没有的,需要完整写 List a。不过,PairUnit 的语法糖仍然存在。(虽然……我用 PairEither 之前铁定会弄俩运算符 /\\/。)
  10. Idris 的 Type class 叫做接口(Interface),对应的实例叫做实现(Implementation)。接口的方法中什么都可以放,包括次级类型。(不过这么做很容易造成编译的时候推不出来就是了……)
  11. 由于箭头是 Binder,因此 Idris 的「->」不是一个正常的类型构造符,也无法实现接口。对于非依赖的函数,Data.Morphism 中定义了 Morphism 类型(符号是 ~>),可以像 Haskell 中的 (->) 那样实现接口。
  12. Idris 允许对于名称的直接重载,像 (::) 就被重载过(Vect.(::), List.(::), Stream.(::))。有时候可能需要显式消歧义来处理推不出来的情况。
  13. Idris 中的 headindex 是不能随便用的,它们的签名中有一个命题项 ok,你得说服编译器「数组不空」或者「没有越界」。如果不想去哄编译器的话,可以用 head'index',它们返回一个 Maybe
  14. 没有 fmapreturn mapM,用 mappure traverse
  15. Haskell 里 Data.Map 对应物是 contrib 包中的 Data.SortedMap,用平衡树实现的。
  16. 因为有 Dependent Type 所以不需要用 Pair 做「链表」模拟 Nat。(这条是说给 @帅气可爱魔理沙 听的。)
  17. deriving 的功能目前由 Elaborator Reflection 元编程实现:derive-all-the-instances。使用的时候需要开启 ElabReflection 扩展。
  18. Idris 默认的导出规则是 private,因此当你需要导出函数的时候请用 export;导出 datainterface 的时候请用 public exportexportpublic export 的区别是,前者只导出其类型,后者会连同定义一起导出。对于类型别名来说,仅仅以 export 导出会导致使用这个别名的模块无法把它和它的本体联系起来。
  19. Haskell 里面的 Guard Pattern 在 Idris 里面可以用 with 实现。
  20. 尽管写证明很美好,不过测试框架还是很有意义的:Idris 中你可以在 ipkg 文件中声明代表测试的模块,然后 idris --testpkg xxx.pkg 会运行这些模块导出的函数进行测试。可以使用 david-christiansen/idris-quickcheck 等模块辅助测试。
  21. 尽管 Idris 有一个 JS 的后端,也有人写了 JavaScript 的 Binding(IdrisScript),不过这个后端也只是能运行罢了……
  22. 网上很多 Idris 编辑器支持的语法文件都停留在几年前(那个没有 rewriteinterface 还叫 class 的年代)。然而 VSCode 的插件——vscode-idris 里面的语法是对的。因为是我改的。
  23. 最后,Idris 里有我的代码,在 RTS 里面。
15 条评论