Idris

维基百科,自由的百科全书
跳转到导航 跳转到搜索
Idris
编程范型函数式编程
设计者Edwin Brady
发行时间2007年,​19年前​(2007[1]
当前版本
    Module:EditAtWikidata第29行Lua错误:attempt to index field 'wikibase' (a nil value)
    型态系统静态类型, 强类型, 依赖类型
    操作系统跨平台
    许可证BSD-3
    文件扩展名.idr, .lidr
    网站Idris
    受影响于
    Agda, Coq, Epigram英语Epigram (programming language), Haskell, ML

    Idris是一个通用的依赖类型纯函数式编程语言,其类型系统Agda以及Epigram英语Epigram (programming language)相似。

    Idris语言具备堪与Coq媲美的交互式定理证明能力,自带tactics,而其设计目标侧重于通用系统编程更甚于辅助证明。Idris的其他设计目标还包括“可观的”代码性能,对副作用的控制,以及对于实现嵌入式领域特定语言(Embedded Domain Specific Language,EDSL)的支持。

    Idris通过一个依赖类型的核心语言TT生成C语言的中间代码并编译到本地机器码,并利用了一个基于Cheney算法垃圾收集器实现。Idris亦拥有 JavaScriptJavaLLVM的编译器后端。[3]

    Idris的名字来自于20世纪70年代的英国儿童动画片《火车头艾弗英语Ivor_the_Engine#Idris_the_Dragon》里,一条会唱歌的[4]

    语言特性[编辑]

    依赖类型[编辑]

    Idris 支持对依赖类型(<math>\lambda \Pi</math>)的定义。如下定义了<math>\mbox{Vec}(a,n)</math>,即元素类型 <math>a</math> 的 <math>n</math>-元组类型:

    data Nat = O | S Nat
    infixr 5 ::
    
    data Vect : Type -> Nat -> Type where
        VNil : Vect a O
      | (::) : a -> Vect a k -> Vect a (S k)
    

    嵌入式领域特定语言(EDSL)[编辑]

    Idris 对嵌入式领域特定语言的支持主要包括以下方面[5]

    1. 编译期间求值。
    2. 重载的语法。
    3. 与C语言库的接口,以及高效的代码生成

    类型提供器(Type Provider)[编辑]

    Idris 拥有与 F# 相似的类型提供器,它允许编译器在编译期间根据所执行代码的需求而生成新的类型信息。这使得静态类型系统更具可扩展性。[6]

    示例[编辑]

    语法[编辑]

    Idris 的语法与 Haskell 有许多相似之处。一个最简单的 Hello World 程序如下:

    module Main
    
    main : IO ()
    main = putStrLn "Hello, World!"
    

    该程序与 Haskell 的等效写法仅有两点不同:类型签名使用单个冒号“:”而不是双冒号“::”;开头的模块声明中不必使用 where 从句。

    Idris 亦支持 where 从句、let 表达式、with 规则、简单的 case 表达式和模式匹配等。

    依赖类型[编辑]

    一个在 Idris 中使用依赖类型的示例:

    total
    append : Vect n a -> Vect m a -> Vect (n + m) a
    append Nil       ys = ys
    append (x :: xs) ys = x :: append xs ys
    

    该函数将一个包含 m 个类型 a 的元素的 vector 连接到一个包含 n 个类型 a 的元素的 vector 之后。由于输入 vector 的确切类型依赖于它的值,故在编译(类型检查)时即可保证输出的 vector 必将包含 (n + m) 个类型 a 的元素。

    关键字“total”将会执行函数的完整性(totality)检查。若函数定义未涵盖所有可能的情形(partial function),则检查器会报错。

    另一个使用依赖类型的示例:

    total
    pairAdd : Num a => Vect n a -> Vect n a -> Vect n a
    pairAdd Nil       Nil       = Nil
    pairAdd (x :: xs) (y :: ys) = x + y :: pairAdd xs ys
    

    Num a 标志着类型 a 属于 Type class英语Type class Num。注意在这里,该函数被认为是完整的(total),尽管并未定义一个参数是 Nil 而另一个参数非 Nil 的模式。原因在于两个作为参数的 vector 只能具备相同的长度,这一点通过依赖类型系统得到了保证,因此在编译时两者长度不同的情形绝无可能发生。这使得该函数定义仍然是完整的。

    求值策略[编辑]

    Idris 默认采取及早求值(Eager evaluation),而非 Haskell 的惰性求值(Lazy evaluation)方式。Idris 支持使用 Lazy 关键字显式地指定惰性求值:

    data Lazy : Type -> Type where
      Delay : (val : a) -> Lazy a
    
    Force : Lazy a -> a
    
    boolCase : Bool -> Lazy a -> Lazy a -> a;
    boolCase True t e = t;
    boolCase False t e = e;
    

    参考文献[编辑]

    1. ^ Brady, Edwin. Index of /~eb/darcs/Idris. University of St Andrews School of Computer Science. 2007-12-12. (原始内容存档于2008-03-20). 
    2. ^ Release 1.3.3. [2020-05-25]. (原始内容存档于2021-02-04). 
    3. ^ Idris - News. [2013-12-24]. (原始内容存档于2013-12-24). 
    4. ^ Idris - FAQ. [2013-12-24]. (原始内容存档于2012-03-11). 
    5. ^ Slides from Systems Programming with Dependent Types at DTP11 (PDF). [永久失效链接]
    6. ^ Christiansen, David. Dependent type providers (PDF). 2013 [2014-08-26]. (原始内容 (PDF)存档于2017-08-09). 

    外部链接[编辑]