comments
-- single-line {- multi-line -}
keywords
case .. of constructor data export if .. then .. else .. implementation import interface let .. in module mutual namespace parameters private public export record total using where
primitive types:
Int Integer Double Char String Bool : True | False Ptr Bits8 Bits16 Bits32 Bits64
ops
+ Int, Double, Bits8, Bits16, Bits32, Bits64 - Int, Double, Bits8, Bits16, Bits32, Bits64 * Int, Double / Double ++ String div Int divBigInt Integer divInt Int mod Int modBigInt Integer modInt Int gcd Int lcm Int || Bool && Bool not Bool /= Eq t == Eq t < Ord t <= Ord t > Ord t >= Ord t max Ord t min Ord t
bits ops
divB8 divB16 divB32 divB64 modB8 modB16 modB32 modB64
type casting
cast : Cast fm to => (orig : fm) -> to the : (a : Type) -> a -> a fromInteger : Num ty => Integer -> ty unpack : String -> List Char
> unpack "ABC" ['A', 'B', 'C']
pack : Foldable t => t Char -> String
> pack ['A', 'B', 'C'] "ABC" : String
-- разделяет строку по пробеламwords : String -> List String
> words " A B C D E " ["A", "B", "C", "D", "E"]
-- склеивает строки, с пробелами-разделителямиunwords : List String -> String
> unwords ["A", "BC", "D", "E"] "A BC D E"
-- разбивает строку по знаку "новой строки"lines : String -> List String
> lines "\rA BC\nD\r\nE\n" ["A BC", "D", "E"]
-- склеивает строки, с разделителями-"новая строка"unlines : List String -> String
> unlines ["line", "line2", "ln3", "D"] "line\nline2\nln3\nD"
b8ToString : Bits8 -> String b16ToString : Bits16 -> String b32ToString : Bits32 -> String b64ToString : Bits64 -> String
modules
файл модуля состоит из
- опциональной декларации module <name> за которой следуют
- опциональный список import <name>
- декларации и определения
программа может состоять из нескольких модулей и каждый из них имеет отдельное пространство имен. имя модуля не обязано совпадать с именем файла, хотя это приветствуется
в декларации import ссылаются на имя файла используя "dots separated directories":
import foo.barимпортирует файл "foo/bar.idr", с его внутренней декларацией:
module foo.barглавный модуль программы должен содержать декларацию module Main и функцию main, а вот имя его не обязано быть Main.idr
функции, типы и интерфейсы могут быть помечены как private, export или public export. по умолчанию все имена модуля являются private
- private
- export экспортируется только самый верхний уровень
- public export
для типов данных:
для интерфейсов:
тип экспорта может быть изменен с помощью директивы %access :
module Btree
%access export
и теперь любая функция без директивы доступа будет иметь тип export, а не private
определив модуль вы определяете и пространство имен. пространства имен могут определяться и явно:
module Foo
namespace x
test : Int -> Int
test x = x * 2
namespace y
test : String -> String
test x = x ++ x
functions
в отличие от Хаскеля в Идрисе и типы и функции могут начинаться как с заглавной, так и со строчной букв - имена функций, конструкторы (данных и типов) находятся в одном пространстве имен
where
локальную функцию можно определить используяwhere. все имена, видимые в самой функции видны и в блоке where. имя, которое определено в сигнатуре, но не в основном теле - будет видно в where если оно является параметром типа. функции, определенные в where требуют сигнатуры
let x = ... in ...
допускается паттерн-матчинг
case ... of ...
функция, вычисляющая тип
f01 : Bool -> Type
f01 True = Nat
f01 False = List Nat
может быть использована как return type
f02 : (x : Bool) -> f01 x
f02 True = 0
f02 False = []
так и в середине сигнатур
f03 : (x : Bool) -> f01 x -> Nat
f03 True y = y
f03 False [] = 0
f03 False (y :: ys) = y + f03 False ys
любое имя со строчной начальной, появляющееся как параметр или индекс в сигнатуре всегда будет неявным аргументом, который может быть задан и явно в теле функции с помощью
f04 : Fin n -> Vect n a -> a
f04 FZ (x :: xs) = x
f04 (FS k) (x :: xs) = g03 k xs
f05 : Int
f05 = g04 {a=Int} {n=2} FZ (2 :: 3 :: Nil)
ключевое слово using позволяет задать сигнатуры для всех НЕЯВНЫХ переменных и типов в декларациях и определениях блока:
using (x : a, y : a, xs : Vect n a)
data Elem : a -> Vect n a -> Type where
Here : Elem x (x :: xs)
There : Elem x xs -> Elem x (y :: xs)
набор функций может быть параметризован аргументами, если используется ключевое слово parameters с перечнем аргументов перед декларацией этих функций:
parameters (x : Nat, y : Nat)
addAll : Nat -> Nat
addAll z = x + y + z
такие параметры передаются ПЕРЕД явными параметрами в каждой функции блока
ключевым словом mutual задается блок взаимно-рекурсивных функций
mutual
even : Nat -> Bool
even Z = True
even (S k) = odd k
odd : Nat -> Bool
odd Z = False
odd (S k) = even k
в Идрисе есть хаскельные "секции":
λΠ> :let z : Vect 5 Int ; z = [1, 2, 3, 4, 5] λΠ> show $ map (* 2) z "[2, 4, 6, 8, 10]" : String
используя ключевое слово total перед декларацией функции можно потребовать от компилятора проверки этой функции на тотальность
tuples
встроенный тип данных:
data Pair : (a : Type) -> (b : Type) -> Type where MkPair : (a : A) -> (b : B) -> (A , B)
синтаксический сахар (a , b) означает либо Pair a b либо MkPair a b - в зависимости от контекста
λΠ> :let x = MkPair 10 "aaa" defined λΠ> x (10, "aaa") : (Integer, String) λΠ> fst x 10 : Integer λΠ> snd x "aaa" : String λΠ> :let y = (True, x) defined λΠ> y (True, 10, "aaa") : (Bool, Int, String) λΠ> :let z = fst (snd y) defined λΠ> z 10 : Int
records
синтакс отличен от Haskell:
record Person where
constructor MkPerson
firstName, middleName, lastName : String
age : Int
member : Bool
fred : Person
fred = MkPerson "Fred" "Joe" "Bloggs" 30 True
каждая запись определяет свое собственное пространство имен, так что имена полей разных записей могут совпадать
jim : Person
jim = record { firstName = "Jim" } fred
синтакс record { field = val, ... } var создает функцию, которая для существующей записи var обновляет указанные поля новыми значениями. поля могут быть зависимыми типами - в этом случае обновление произойдет только если результат имеет правильный тип
IO
show : Show a => a -> String print : Show a => a -> IO () printLn : Show a => a -> IO () putStr : String -> IO () putStrLn : String -> IO () putChar : Char -> IO () putCharLn : Char -> IO () getLine : IO String getChar : IO Char getArgs : IO (List String) data File : Type where FHandle : (p : Ptr) -> File data Mode : Type Read : Mode WriteTruncate : Mode Append : Mode ReadWrite : Mode ReadWriteTruncate : Mode ReadAppend : Mode readFile : String -> IO (Either FileError String) writeFile : (path : String) -> (contents : String) -> IO (Either FileError ()) data FileError : Type FileReadError : FileError FileWriteError : FileError FileNotFound : FileError PermissionDenied : FileError GenericFileError : Int -> FileError openFile : (name : String) -> (mode : Mode) -> IO (Either FileError File) fGetLine : (h : File) -> IO (Either FileError String) fPutStr : (h : File) -> (str : String) -> IO (Either FileError ()) fEOF : File -> IO Bool closeFile : File -> IO ()
интерфейсы и их имплементации
ключевое словоinterface определяет блок, содержащий обязательные сигнатуры класса, а ключевое слово implementation определяет блок, в котором прописаны реализации. чтобы определить реализацию класса, нужно задать все методы, указанные в интерфейсе этого класса. реализация может быть и расширена - то есть включать не только обязательные, но и дополнительные методы
для данного типа может быть определена лишь одна реализация интерфейса, а если все же нужны разные реализации, то можно их сделать именованными:
[myord] Ord Nat where
compare Z (S n) = GT
compare (S n) Z = LT
compare Z Z = EQ
compare (S x) (S y) = compare @{myord} x y
λΠ> :let testList : List Nat testList : List Nat λΠ> :let testList = [3,4,1] λΠ> show (sort testList) "[sO, sssO, ssssO]" : String λΠ> show (sort @{myord} testList) "[ssssO, sssO, sO]" : String
декларации реализаций могут иметь ограничения, которые записываются в скобках, через запятую. аргументами должны быть конструкторы (типов или данных), переменные или константы. нельзя определить реализацию для функции
два элиминатора
maybe : Lazy b -> Lazy (a -> b) -> Maybe a -> b either : (f : Lazy (a -> c)) -> (g : Lazy (b -> c)) -> (e : Either a b) -> c
No comments:
Post a Comment