mirror of
https://github.com/edwinb/Idris2-boot.git
synced 2024-11-30 22:05:32 +03:00
Add Range interface to prelude
This is part of what we used to have in Enum but I think it's better to separate the two. Added implementations for Nat, and anything in Integral/Ord/Neg, so that we get range syntax (at least when its implemeted) for the most useful cases.
This commit is contained in:
parent
1cf9849a55
commit
4860d2b751
@ -31,12 +31,6 @@ isItSucc : (n : Nat) -> Dec (IsSucc n)
|
|||||||
isItSucc Z = No absurd
|
isItSucc Z = No absurd
|
||||||
isItSucc (S n) = Yes ItIsSucc
|
isItSucc (S n) = Yes ItIsSucc
|
||||||
|
|
||||||
public export
|
|
||||||
minus : Nat -> Nat -> Nat
|
|
||||||
minus Z right = Z
|
|
||||||
minus left Z = left
|
|
||||||
minus (S left) (S right) = minus left right
|
|
||||||
|
|
||||||
public export
|
public export
|
||||||
power : Nat -> Nat -> Nat
|
power : Nat -> Nat -> Nat
|
||||||
power base Z = S Z
|
power base Z = S Z
|
||||||
|
@ -574,6 +574,12 @@ plus : Nat -> Nat -> Nat
|
|||||||
plus Z y = y
|
plus Z y = y
|
||||||
plus (S k) y = S (plus k y)
|
plus (S k) y = S (plus k y)
|
||||||
|
|
||||||
|
public export
|
||||||
|
minus : Nat -> Nat -> Nat
|
||||||
|
minus Z right = Z
|
||||||
|
minus left Z = left
|
||||||
|
minus (S left) (S right) = minus left right
|
||||||
|
|
||||||
public export
|
public export
|
||||||
mult : Nat -> Nat -> Nat
|
mult : Nat -> Nat -> Nat
|
||||||
mult Z y = Z
|
mult Z y = Z
|
||||||
@ -1298,3 +1304,80 @@ export
|
|||||||
Cast Nat Double where
|
Cast Nat Double where
|
||||||
cast = prim__cast_IntegerDouble . natToInteger
|
cast = prim__cast_IntegerDouble . natToInteger
|
||||||
|
|
||||||
|
------------
|
||||||
|
-- RANGES --
|
||||||
|
------------
|
||||||
|
|
||||||
|
countFrom : n -> (n -> n) -> Stream n
|
||||||
|
countFrom start diff = start :: countFrom (diff start) diff
|
||||||
|
|
||||||
|
partial
|
||||||
|
takeUntil : (n -> Bool) -> Stream n -> List n
|
||||||
|
takeUntil p (x :: xs)
|
||||||
|
= if p x
|
||||||
|
then [x]
|
||||||
|
else x :: takeUntil p xs
|
||||||
|
|
||||||
|
partial
|
||||||
|
takeBefore : (n -> Bool) -> Stream n -> List n
|
||||||
|
takeBefore p (x :: xs)
|
||||||
|
= if p x
|
||||||
|
then []
|
||||||
|
else x :: takeBefore p xs
|
||||||
|
|
||||||
|
public export
|
||||||
|
interface Range a where
|
||||||
|
rangeFromTo : a -> a -> List a
|
||||||
|
rangeFromThenTo : a -> a -> a -> List a
|
||||||
|
|
||||||
|
rangeFrom : a -> Stream a
|
||||||
|
rangeFromThen : a -> a -> Stream a
|
||||||
|
|
||||||
|
-- Idris 1 went to great lengths to prove that these were total. I don't really
|
||||||
|
-- think it's worth going to those lengths! Let's keep it simple and assert.
|
||||||
|
export
|
||||||
|
Range Nat where
|
||||||
|
rangeFromTo x y
|
||||||
|
= if y > x
|
||||||
|
then assert_total $ takeUntil (>= y) (countFrom x S)
|
||||||
|
else if x > y
|
||||||
|
then assert_total $ takeUntil (<= y) (countFrom x (\n => minus n 1))
|
||||||
|
else [x]
|
||||||
|
rangeFromThenTo x y z
|
||||||
|
= if y > x
|
||||||
|
then (if z > x
|
||||||
|
then assert_total $ takeBefore (> z) (countFrom x (plus (minus y x)))
|
||||||
|
else [])
|
||||||
|
else (if x == y
|
||||||
|
then (if x == z then [x] else [])
|
||||||
|
else assert_total $ takeBefore (< z) (countFrom x (\n => minus n (minus x y))))
|
||||||
|
rangeFrom x = countFrom x S
|
||||||
|
rangeFromThen x y
|
||||||
|
= if y > x
|
||||||
|
then countFrom x (plus (minus y x))
|
||||||
|
else countFrom x (\n => minus n (minus x y))
|
||||||
|
|
||||||
|
export
|
||||||
|
(Integral a, Ord a, Neg a) => Range a where
|
||||||
|
rangeFromTo x y
|
||||||
|
= if y > x
|
||||||
|
then assert_total $ takeUntil (>= y) (countFrom x (+1))
|
||||||
|
else if x > y
|
||||||
|
then assert_total $ takeUntil (<= y) (countFrom x (\x => x-1))
|
||||||
|
else [x]
|
||||||
|
rangeFromThenTo x y z
|
||||||
|
= if (z - x) > (z - y)
|
||||||
|
then -- go up
|
||||||
|
assert_total $ takeBefore (> z) (countFrom x (+ (y-x)))
|
||||||
|
else if (z - x) < (z - y)
|
||||||
|
then -- go down
|
||||||
|
assert_total $ takeBefore (< z) (countFrom x (\n => n - (x - y)))
|
||||||
|
else -- meaningless
|
||||||
|
if x == y && y == z
|
||||||
|
then [x] else []
|
||||||
|
rangeFrom x = countFrom x (1+)
|
||||||
|
rangeFromThen x y
|
||||||
|
= if y > x
|
||||||
|
then countFrom x (+ (y - x))
|
||||||
|
else countFrom x (\n => n - (x - y))
|
||||||
|
|
||||||
|
@ -270,6 +270,23 @@ mutual
|
|||||||
toPure tm = DoExp fc (PApp fc (PRef fc (UN "pure")) tm)
|
toPure tm = DoExp fc (PApp fc (PRef fc (UN "pure")) tm)
|
||||||
desugar side ps (PRewrite fc rule tm)
|
desugar side ps (PRewrite fc rule tm)
|
||||||
= pure $ IRewrite fc !(desugar side ps rule) !(desugar side ps tm)
|
= pure $ IRewrite fc !(desugar side ps rule) !(desugar side ps tm)
|
||||||
|
desugar side ps (PRange fc start next end)
|
||||||
|
= case next of
|
||||||
|
Nothing =>
|
||||||
|
desugar side ps (PApp fc
|
||||||
|
(PApp fc (PRef fc (UN "rangeFromTo"))
|
||||||
|
start) end)
|
||||||
|
Just n =>
|
||||||
|
desugar side ps (PApp fc
|
||||||
|
(PApp fc
|
||||||
|
(PApp fc (PRef fc (UN "rangeFromThenTo"))
|
||||||
|
start) n) end)
|
||||||
|
desugar side ps (PRangeStream fc start next)
|
||||||
|
= case next of
|
||||||
|
Nothing =>
|
||||||
|
desugar side ps (PApp fc (PRef fc (UN "rangeFrom")) start)
|
||||||
|
Just n =>
|
||||||
|
desugar side ps (PApp fc (PApp fc (PRef fc (UN "rangeFromThen")) start) n)
|
||||||
|
|
||||||
desugarUpdate : {auto s : Ref Syn SyntaxInfo} ->
|
desugarUpdate : {auto s : Ref Syn SyntaxInfo} ->
|
||||||
{auto c : Ref Ctxt Defs} ->
|
{auto c : Ref Ctxt Defs} ->
|
||||||
|
@ -823,7 +823,7 @@ dataOpt
|
|||||||
dataBody : FileName -> Int -> FilePos -> Name -> IndentInfo -> PTerm ->
|
dataBody : FileName -> Int -> FilePos -> Name -> IndentInfo -> PTerm ->
|
||||||
EmptyRule PDataDecl
|
EmptyRule PDataDecl
|
||||||
dataBody fname mincol start n indents ty
|
dataBody fname mincol start n indents ty
|
||||||
= do atEnd indents
|
= do atEndIndent indents
|
||||||
end <- location
|
end <- location
|
||||||
pure (MkPLater (MkFC fname start end) n ty)
|
pure (MkPLater (MkFC fname start end) n ty)
|
||||||
<|> do keyword "where"
|
<|> do keyword "where"
|
||||||
|
@ -82,6 +82,10 @@ mutual
|
|||||||
PIfThenElse : FC -> PTerm -> PTerm -> PTerm -> PTerm
|
PIfThenElse : FC -> PTerm -> PTerm -> PTerm -> PTerm
|
||||||
PComprehension : FC -> PTerm -> List PDo -> PTerm
|
PComprehension : FC -> PTerm -> List PDo -> PTerm
|
||||||
PRewrite : FC -> PTerm -> PTerm -> PTerm
|
PRewrite : FC -> PTerm -> PTerm -> PTerm
|
||||||
|
-- A list range [x,y..z]
|
||||||
|
PRange : FC -> PTerm -> Maybe PTerm -> PTerm -> PTerm
|
||||||
|
-- A stream range [x,y..]
|
||||||
|
PRangeStream : FC -> PTerm -> Maybe PTerm -> PTerm
|
||||||
|
|
||||||
-- TODO: Ranges, idiom brackets (?),
|
-- TODO: Ranges, idiom brackets (?),
|
||||||
-- 'with' disambiguation
|
-- 'with' disambiguation
|
||||||
@ -425,6 +429,14 @@ mutual
|
|||||||
deGuard tm = tm
|
deGuard tm = tm
|
||||||
show (PRewrite _ rule tm)
|
show (PRewrite _ rule tm)
|
||||||
= "rewrite " ++ show rule ++ " in " ++ show tm
|
= "rewrite " ++ show rule ++ " in " ++ show tm
|
||||||
|
show (PRange _ start Nothing end)
|
||||||
|
= "[" ++ show start ++ " .. " ++ show end ++ "]"
|
||||||
|
show (PRange _ start (Just next) end)
|
||||||
|
= "[" ++ show start ++ ", " ++ show next ++ " .. " ++ show end ++ "]"
|
||||||
|
show (PRangeStream _ start Nothing)
|
||||||
|
= "[" ++ show start ++ " .. ]"
|
||||||
|
show (PRangeStream _ start (Just next))
|
||||||
|
= "[" ++ show start ++ ", " ++ show next ++ " .. ]"
|
||||||
|
|
||||||
public export
|
public export
|
||||||
record IFaceInfo where
|
record IFaceInfo where
|
||||||
|
@ -360,6 +360,7 @@ init = 0
|
|||||||
continueF : EmptyRule () -> (indent : IndentInfo) -> EmptyRule ()
|
continueF : EmptyRule () -> (indent : IndentInfo) -> EmptyRule ()
|
||||||
continueF err indent
|
continueF err indent
|
||||||
= do eoi; err
|
= do eoi; err
|
||||||
|
<|> do keyword "where"; err
|
||||||
<|> do col <- column
|
<|> do col <- column
|
||||||
if (col <= indent)
|
if (col <= indent)
|
||||||
then err
|
then err
|
||||||
@ -409,6 +410,7 @@ isTerminator (Symbol "}") = True
|
|||||||
isTerminator (Symbol ")") = True
|
isTerminator (Symbol ")") = True
|
||||||
isTerminator (Symbol "|") = True
|
isTerminator (Symbol "|") = True
|
||||||
isTerminator (Keyword "in") = True
|
isTerminator (Keyword "in") = True
|
||||||
|
isTerminator (Keyword "where") = True
|
||||||
isTerminator EndInput = True
|
isTerminator EndInput = True
|
||||||
isTerminator _ = False
|
isTerminator _ = False
|
||||||
|
|
||||||
@ -427,6 +429,17 @@ atEnd indent
|
|||||||
then pure ()
|
then pure ()
|
||||||
else fail "Not the end of a block entry"
|
else fail "Not the end of a block entry"
|
||||||
|
|
||||||
|
-- Check we're at the end, but only by looking at indentation
|
||||||
|
export
|
||||||
|
atEndIndent : (indent : IndentInfo) -> EmptyRule ()
|
||||||
|
atEndIndent indent
|
||||||
|
= eoi
|
||||||
|
<|> do col <- column
|
||||||
|
if (col <= indent)
|
||||||
|
then pure ()
|
||||||
|
else fail "Not the end of a block entry"
|
||||||
|
|
||||||
|
|
||||||
-- Parse a terminator, return where the next block entry
|
-- Parse a terminator, return where the next block entry
|
||||||
-- must start, given where the current block entry started
|
-- must start, given where the current block entry started
|
||||||
terminator : ValidIndent -> Int -> EmptyRule ValidIndent
|
terminator : ValidIndent -> Int -> EmptyRule ValidIndent
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
1/1: Building Total (Total.idr)
|
1/1: Building Total (Total.idr)
|
||||||
Welcome to Idris 2 version 0.0. Enjoy yourself!
|
Welcome to Idris 2 version 0.0. Enjoy yourself!
|
||||||
Main> Main.count is total
|
Main> Main.count is total
|
||||||
Main> Main.badCount is not terminating due to recursive path Main.badCount -> Prelude.Functor implementation at Prelude.idr:810:1--814:1 -> Prelude.map
|
Main> Main.badCount is not terminating due to recursive path Main.badCount -> Prelude.Functor implementation at Prelude.idr:816:1--820:1 -> Prelude.map
|
||||||
Main> Main.process is total
|
Main> Main.process is total
|
||||||
Main> Main.badProcess is not terminating due to recursive path Main.badProcess -> Main.badProcess -> Main.badProcess
|
Main> Main.badProcess is not terminating due to recursive path Main.badProcess -> Main.badProcess -> Main.badProcess
|
||||||
Main> Main.doubleInt is total
|
Main> Main.doubleInt is total
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
1/1: Building ArithState (ArithState.idr)
|
1/1: Building ArithState (ArithState.idr)
|
||||||
1/1: Building DataStore (DataStore.idr)
|
1/1: Building DataStore (DataStore.idr)
|
||||||
1/1: Building Record (Record.idr)
|
1/1: Building Record (Record.idr)
|
||||||
|
1/1: Building State (State.idr)
|
||||||
1/1: Building StateMonad (StateMonad.idr)
|
1/1: Building StateMonad (StateMonad.idr)
|
||||||
1/1: Building Traverse (Traverse.idr)
|
1/1: Building Traverse (Traverse.idr)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
$1 ArithState.idr --check
|
$1 ArithState.idr --check
|
||||||
$1 DataStore.idr --check
|
$1 DataStore.idr --check
|
||||||
$1 Record.idr --check
|
$1 Record.idr --check
|
||||||
# $1 State.idr --check
|
$1 State.idr --check
|
||||||
$1 StateMonad.idr --check
|
$1 StateMonad.idr --check
|
||||||
$1 Traverse.idr --check
|
$1 Traverse.idr --check
|
||||||
# $1 TreeLabel.idr --check
|
# $1 TreeLabel.idr --check
|
||||||
|
Loading…
Reference in New Issue
Block a user