Zulip Chat Archive

Stream: lean4

Topic: vectors in lean4


Frederic Peschanski (Jun 21 2022 at 15:04):

In the "Theorem proving with Lean4" book there is an inductive for Vectors in the section on "Inductive families". I looked at the standard library but no vectors there. Did someone tried to implement the basic operations on vectors : append, fromList, toList, etc. ? I must confess I am stuck with these basic things.

Henrik Böving (Jun 21 2022 at 15:47):

The area you are talking about are so called "length indexed lists" (indexed is a type theory, not a list term here), the standard library is however just a piece of code that the compiler requires in order to bootstrap itself right now so don't expect too fancy things from it. I have a few operations I translated from the coq code in CPDT (this book: http://adam.chlipala.net/cpdt/cpdt.pdf) here: https://github.com/hargoniX/cpdt-lean/blob/main/Cpdt/Chapter8/LengthIndexed.lean but nothing too fancy.

If you have more concrete questions just ask here, we're happy to help.

Frederic Peschanski (Jun 22 2022 at 09:54):

Thank you @Henrik Böving this gives me a starting point ... I see that subtypes could be useful ...

Andrés Goens (Jun 24 2022 at 05:02):

I've a follow-up question/kind of in the same spirit. If I wanted to express more complex properties in the type like this, say, for ordered lists, is there a way to encode it in the type, the same way? My naive attempt at this doesn't work

inductive OrderedList (α : Type) [LE α]
  | OrderedNil : OrderedList α
  | OrederedCons (a : α) (as : OrderedList α) (h : match as with | OrderedNil => True | OrderedCons b _ => a  b)

I suppose that the construction isn't in scope yet in its own constraint. Is there a way to express a constraint like this? I suppose I can "split it up" like so

def OrderedList (α : Type) [LE α] : List α  Prop
  | a::b::rest => a  b  OrderedList α (b::rest)
  | _ => True

But that's somewhat unsatisfactory, as we don't get the same types of guarantees with the type as we do for length-indexed lists (i.e. correct by construction)

Henrik Böving (Jun 24 2022 at 07:25):

If you define a notion of membership for a list like mathlib (docs4#List.Mem) you can (in the cons case) say something like (h : ∀ y, y ∈ as → a ≤ y)

Evgeniy Kuznetsov (Jun 24 2022 at 10:41):

inductive OrderedList' (α : Type) [LE α]: Option α  Type
| nil: OrderedList' α .none
| cons_nil  (a: α) (as: OrderedList' α $ .none  )           : OrderedList' α (.some a)
| cons_cons (a: α) (as: OrderedList' α $ .some b) (_: a  b): OrderedList' α (.some a)

def OrderedList (α : Type) [LE α] := (head: Option α) × OrderedList' α head

Andrés Goens (Jun 24 2022 at 14:35):

ahh, you're "remembering" the item at the head with the type, that's a really cool solution!

Tomas Skrivan (Jun 24 2022 at 17:19):

What is the problem with defining inductively a Prop that the list is ordered and then OrderedList is just a Subtype of List?

The only complicated thing is how to write a match statements with this type. You definitely want to match on the List and the Prop at the same time.

François G. Dorais (Jun 24 2022 at 20:52):

You can try using @[matchPattern] to define your own patterns:

def List.precede {α} [LE α] (x : α) : List α  Prop
| [] => True
| y::_ => x  y

inductive IsOrdered {α} [LE α] : List α  Type
| nil : IsOrdered []
| cons {x xs} : List.precede x xs  IsOrdered xs  IsOrdered (x :: xs)

def OrderedList (α) [LE α] := (xs : List α) × IsOrdered xs

@[matchPattern]
def OrderedList.nil {α} [LE α] : OrderedList α := ⟨[], IsOrdered.nil

@[matchPattern]
def OrderedList.cons {α} [LE α] (x : α) (xs : List α) (h : List.precede x xs) (hs : IsOrdered xs) : OrderedList α := x :: xs, IsOrdered.cons h hs

def matchTest {α} [LE α] : OrderedList α  Nat
| OrderedList.nil => 0
| OrderedList.cons _ _ _ _ => 0

Mac (Jun 25 2022 at 05:44):

Tomas Skrivan said:

What is the problem with defining inductively a Prop that the list is ordered and then OrderedList is just a Subtype of List?

The only complicated thing is how to write a match statements with this type.

This is the big problem with subtypes (and propositions in general) when it comes to programming. Most natural pattern matching, structural recursion, type class deriving (e.g., Inhabited), namespacing, etc. is broken and thus requires lots of proving and other manual work to fix (instead of things "just working").

Don't get me wrong the tools (subtypes and proofs) are powerful, they are just often best reserved for when they are needed and use other, more convenient, approaches when possible (in the programming context at least).

Frederic Peschanski (Jun 30 2022 at 14:52):

I played a little bit more with vectors, still based on the following definition :

inductive Vector (A : Type) : Nat  Type u where
  | vnil  : Vector A 0
  | vcons : A  {n : Nat}  Vector A n  Vector A (n+1)
   deriving Repr

... I have something I don't undestand perfectly below:

def vindex {A : Type} {n : Nat} (fin : Fin n) (v : Vector A n) : A :=
  match (fin, v) with
  | (⟨0,_ , vcons e _) => e
  | (⟨m+1,hk⟩, vcons _ v') => vindex m,by apply Nat.lt_of_succ_lt_succ ; exact hk v'

Seems fine (from my naive point of view)...

def v : Vector Nat 4 := vcons 1 (vcons 2 (vcons 3 (vcons 4 vnil)))
#eval vindex 2 v4 -- => 3
#eval vindex 3 v4 -- => 4

But ... oops

#eval vindex 4 v4 -- => 1
#eval vindex 5 v4 -- => 2

... not exactly what I intended :smiling_face:
Could someone explain me what happens here (probably this is not the Fin I imagined) ?
Also if you have a better proposition for vindex I would be interested

Jannis Limperg (Jun 30 2022 at 14:59):

Literals for Fin n are interpreted modulo n. So 4 : Fin 4 is 0, 5 : Fin 4is 1. Arguably Lean should throw an error instead, but that doesn't play well with how these literals are implemented.

Frederic Peschanski (Jun 30 2022 at 16:47):

Thank you @Jannis Limperg I understand now the issue. Probably I will play a little bit with a variant, such as Bound n with the behavior I'm expecting (a type error). However then I don't really understand when one would like to use Fin (at least in my understanding on why and when it's useful...).

Henrik Böving (Jun 30 2022 at 16:59):

When you want to make mathematical arguments about numbers mod n of course.

Eric Wieser (Jun 30 2022 at 17:03):

There are two potentially separate problems at play here:

  1. What should 5 : fin 4 parse as?
  2. What is the value of (3 : fin 4) + (2 : fin 4)?

I think there are technical limitations which make it hard to emit an error for 1, while 2 is chosen because it's as good an option as any

Frederic Peschanski (Jun 30 2022 at 17:13):

... and then maybe (Mod n) would be a better name ? (Fin is already quite connoted in dependent type theory, no ?)

Yakov Pechersky (Jun 30 2022 at 17:27):

We should have a glossary or faq entry for the nuances of fin, vs bounded (unallowed) finite numbers, vs ones with saturated ops, etc.

Mac (Jun 30 2022 at 20:44):

It should also be noted that Fin is used to implemented native fixed-sized (finite) unsigned integers -- UInt8, UInt16, UInt32, UInt64. Mathematically, though, that is also just modular arithmetic (assuming wrapping under/overflow as opposed to trapping under/overflow), so the name Mod n would still fit there too.

Tomas Skrivan (Jun 30 2022 at 21:32):

Also when indexing arrays shouldn't we use some variant of Fin n that is based on USize instead of Nat. Why pay for arbitrary large integers if they can be a meaningful memory address?

Mac (Jun 30 2022 at 23:04):

@Tomas Skrivan Nat only uses arbitrary-sized integers if the value is over a certain threshold (e.g., word-size - 1 bits) otherwise it only consumes one word. Also, many of the Array functions do take advantage of the fact that Arrays are at max USize. There is even a variant of Array.get that does just that (Array.uget).

Tomas Skrivan (Jun 30 2022 at 23:05):

Sure, but if you look at the generated C code then Nat gets passed through a pointer but USize is passed by value.

Mac (Jun 30 2022 at 23:05):

One of the advantages of the Conditional approach @Sebastian Ullrich suggested for getOp is that it could use USize instead of Fin for Array indexing.

Mac (Jun 30 2022 at 23:06):

Tomas Skrivan said:

Sure, but if you look at the generated C code then Nat gets passed through a pointer but USize is passed by value.

The lean_object* is not actually always a pointer. It can actually be either lean_object* OR a raw Nat (if the lower order bit is 1).

Mac (Jun 30 2022 at 23:08):

Such a pointer trick is actually a familiar idea in language design (e.g., Ruby's C implementation does a similar trick for Fixnum, True, False, and Nil).

Tomas Skrivan (Jun 30 2022 at 23:17):

Ohh I was not aware of that. I saw the pointer and updates on the reference counter in the C code. Assumed that it is not ideal and should use USize instead.

Joe Hendrix (Jun 30 2022 at 23:50):

I have a simple vector datatype used for a Lean crypto library that I am working on in my spare time. Polymorphic vectors are in this file, and are a subtype of Array. There's also byte vectors and bitvectors (which use Fin).

Joe Hendrix (Jun 30 2022 at 23:51):

It'd be nice to have a rich set of linear algebra operations and transforms such as scans for array-oriented programming.

Frederic Peschanski (Jul 01 2022 at 13:01):

Here's an ugly version ...

def vindex {A : Type} : {n : Nat}  (k : Nat)  (p : k < n)  (v : Vector A n)  A
  | .(_), 0, .(_), vcons e _ => e
  | n+1, m+1, .(_), vcons _ v' => let p' : m < n := by apply Nat.lt_of_succ_lt_succ ; assumption
                                  @vindex _ _ m p' v'

def v : Vector Nat 4 := vcons 1 (vcons 2 (vcons 3 (vcons 4 vnil)))
#eval vindex 2 (by simp) v -- => 3
#eval vindex 3 (by simp) v -- => 4

#check vindex 4 _ v -- crash !
[Error - 14:55:12] Request textDocument/foldingRange failed.
  Message: Server process for file:///<...>/Vectors.lean crashed, likely due to a stack overflow in user code.
  Code: -32603

Frederic Peschanski (Jul 01 2022 at 13:02):

(no need to say that I navigate by sight :sweat_smile: )

Leonardo de Moura (Jul 01 2022 at 13:11):

@Frederic Peschanski Could you please try the Lean latest nightly build? If it does not fix the problem, could you please create a #mwe?
I tried the following using the code fragments above, and it works in the latest nightly build

inductive Vector (A : Type) : Nat  Type u where
  | vnil  : Vector A 0
  | vcons : A  {n : Nat}  Vector A n  Vector A (n+1)
   deriving Repr

namespace Vector

def vindex {A : Type} : {n : Nat}  (k : Nat)  (p : k < n)  (v : Vector A n)  A
  | .(_), 0, .(_), vcons e _ => e
  | n+1, m+1, .(_), vcons _ v' => let p' : m < n := by apply Nat.lt_of_succ_lt_succ ; assumption
                                  @vindex _ _ m p' v'

def v : Vector Nat 4 := vcons 1 (vcons 2 (vcons 3 (vcons 4 vnil)))
#eval vindex 2 (by simp) v -- => 3
#eval vindex 3 (by simp) v -- => 4

#check vindex 4 _ v -- vindex 4 ?m v : Nat

Frederic Peschanski (Jul 01 2022 at 13:48):

@Leonardo de Moura I've just elan update'd and I can confirm it does not crash anymore with 4.0.0-nightly-2022-07-01, sorry for the false alarm.

cognivore (Jul 27 2022 at 21:36):

(deleted)

Locria Cyber (Jul 30 2022 at 12:17):

Vector isn't in Lean 4 yet

Locria Cyber (Jul 30 2022 at 12:17):

Is contribution welcome or not (adding Vector to Init.Data.Vector)?

Henrik Böving (Jul 30 2022 at 12:19):

Contributions to the Core libraries are in general not welcome unless the additions are required for something in the compilers since the todo list of the compiler team is overhelming already. You can contribute it to mathlib4 though

Locria Cyber (Jul 30 2022 at 12:20):

mathlib still don't have Vector? I was suprised

Locria Cyber (Jul 30 2022 at 12:21):

oh I think Github added a "clone master branch only" (option) when forking

Arthur Paulino (Jul 30 2022 at 12:22):

Mathlib4 is still very rudimentary at this point.

Such PRs are also welcome here: https://github.com/yatima-inc/YatimaStdLib.lean. We're focusing on algorithms and data structures, mostly

Locria Cyber (Jul 30 2022 at 12:24):

What's Yamata Inc?

Locria Cyber (Jul 30 2022 at 12:27):

https://github.blog/changelog/2022-07-27-you-can-now-fork-a-repo-and-copy-only-the-default-branch/

Locria Cyber (Jul 30 2022 at 12:27):

I have a bad feeling about this

Henrik Böving (Jul 30 2022 at 12:29):

Why? Big projects tend to have 100s of branches and if you need any of them you can still fetch them from the other remote regardless

Arthur Paulino (Jul 30 2022 at 12:30):

@Locria Cyber Yatima Inc is an R&D company lead by @John Burnham that develops open source technology, currently using Lean 4 in its stack

Locria Cyber (Jul 30 2022 at 12:38):

Henrik Böving said:

Why? Big projects tend to have 100s of branches and if you need any of them you can still fetch them from the other remote regardless

It's on github clone, not github to local.

Maybe Github is paving the way for its clound-based "workspace".

Locria Cyber (Jul 30 2022 at 12:40):

Also, I had some trouble here. Seems like :: and [term*]must be a typeclass in core for this to work

inductive Vector (α : Type u) : Nat  Type u
  | nil : Vector α 0
  | cons : α  Vector α n  Vector α (n+1)

infix:67 " :: " => Vector.cons

def a := 1 :: Vector.nil
ambiguous, possible interpretations
  1 :: Vector.nil : Vector ?m.1893 (?m.1894 + 1)

  1 :: ?m.1958 : List ?m.1914

Locria Cyber (Jul 30 2022 at 12:41):

def a : Vector Nat _ := 1 :: Vector.nil

error:

don't know how to synthesize placeholder
context:
 Nat
when the resulting type of a declaration is explicitly provided, all holes (e.g., `_`) in the header are resolved before the declaration body is processed

Locria Cyber (Jul 30 2022 at 12:42):

I do need to unify a's type with declaration though.

Henrik Böving (Jul 30 2022 at 12:45):

Locria Cyber said:

def a : Vector Nat _ := 1 :: Vector.nil

error:

don't know how to synthesize placeholder
context:
 Nat
when the resulting type of a declaration is explicitly provided, all holes (e.g., `_`) in the header are resolved before the declaration body is processed

This is the way it is supposed to work, the idea is that if you explicitly denote the type of a you are supposed to provide all arguments to that type explicitly which is a good thing IMO, if you are doing an explicit type you should go through with it

Locria Cyber (Jul 30 2022 at 12:49):

what if I do want to get the length from compiler?

Henrik Böving (Jul 30 2022 at 12:57):

def a := (1 :: Vector.nil : Vector Nat _)

this would work as long as :: isn't TC

Locria Cyber (Jul 30 2022 at 13:14):

thanks

Locria Cyber (Jul 30 2022 at 13:14):

h: a :: as = b :: bs
habs': a = b
 as = bs

Locria Cyber (Jul 30 2022 at 13:14):

question: how do I prove this?

Locria Cyber (Jul 30 2022 at 13:15):

:: is the constructor for Vect

Henrik Böving (Jul 30 2022 at 13:16):

by injectivity of constructor applications:

example (a b : α) (as bs : List α) (h1 : a :: as = b :: bs) (h2 : a = b) : as = bs := by
  injection h1
  assumption

Locria Cyber (Jul 30 2022 at 13:22):

thanks!

Locria Cyber (Jul 30 2022 at 13:22):

instance : SizeOf (Vect α n) where
  sizeOf _ := n

Is this a correct use of SizeOf?

Henrik Böving (Jul 30 2022 at 13:29):

Lean should have already synthesized a SizeOf instance for you automatically that does at least yield the same result though via structural recursion instead of directly getting the n argument.

Locria Cyber (Jul 30 2022 at 13:31):

ok

Henrik Böving (Jul 30 2022 at 13:31):

Ah actually no it didnt

Locria Cyber (Jul 30 2022 at 13:32):

I think by default it's all 0

Locria Cyber (Jul 30 2022 at 13:32):

Also, why is Fin so complicated?

Locria Cyber (Jul 30 2022 at 13:32):

In Idris2, all the data types are their own type, and it's easier to reason about.

Locria Cyber (Jul 30 2022 at 13:33):

don't know how to synthesize placeholder for argument 'isLt'
context:
α : Type u_1
n : Nat
x : α
xs : Vect α n
n : Nat
prf : Nat.succ n < n + 1
value : α
 n < n

Henrik Böving (Jul 30 2022 at 13:33):

Locria Cyber said:

I think by default it's all 0

That is not correct, yes the default SizeOf instance is 0 but lean generate an additional SizeOf instance for all inductive and structure declarations automatically while elaborating them, in the case of your Vector this is:

Vector.rec 1 (fun {n} a a_1 a_ih => 1 + sizeOf n + sizeOf a + a_ih) t

Locria Cyber (Jul 30 2022 at 13:34):

ok

Locria Cyber (Jul 30 2022 at 13:35):

Maybe I should make Nat literal its own type class, and make a new simpler Fin.

Henrik Böving (Jul 30 2022 at 13:35):

Locria Cyber said:

Also, why is Fin so complicated?

Fin isn't complicated its definition is:

structure Fin (n : Nat) where
  val  : Nat
  isLt : LT.lt val n

which is pretty printed more like

structure Fin (n : Nat) where
  val  : Nat
  isLt : val < n

It's just that arguing about Fin while doing recursion on the n argument is icky

Henrik Böving (Jul 30 2022 at 13:35):

Locria Cyber said:

Maybe I should make Nat literal its own type class, and make a new simpler Fin.

Nat literals are already managed by the OfNat typeclass

Locria Cyber (Jul 30 2022 at 13:36):

interesting

Mario Carneiro (Jul 30 2022 at 13:36):

your goal earlier should be something like Nat.lt_of_succ_lt_succ prf

Locria Cyber (Jul 30 2022 at 13:36):

Here's Fin in Idris2:

data Data.Fin.Fin : Nat -> Type
  Numbers strictly less than some bound. The name comes from "finite sets".

  It's probably not a good idea to use `Fin` for arithmetic, and they will be
  exceedingly inefficient at run time.
  @ n the upper bound
  Totality: total
  Visibility: public export
  Constructors:
    FZ : Fin (S k)
    FS : Fin k -> Fin (S k)

Locria Cyber (Jul 30 2022 at 13:37):

This is much easier to reason about

Locria Cyber (Jul 30 2022 at 13:37):

Because I only need to get from Fin (S k) to Fin k (in recursion).

Mario Carneiro (Jul 30 2022 at 13:38):

It's a lot harder to work with equalities in the index with that representation

Mario Carneiro (Jul 30 2022 at 13:38):

in mathlib there are API lemmas for the FZ and FS constructors

Mario Carneiro (Jul 30 2022 at 13:38):

it's pretty easy to define them

Locria Cyber (Jul 30 2022 at 13:38):

equalitiies in the index?

Henrik Böving (Jul 30 2022 at 13:38):

I imagine you could even build a custom induction principle that reflects them, there is no reason to build a new type really

Mario Carneiro (Jul 30 2022 at 13:39):

stuff like Fin (m + n) -> Fin (n + m)

Locria Cyber (Jul 30 2022 at 13:39):

I'm newbie to Lean though

Locria Cyber (Jul 30 2022 at 13:39):

Mario Carneiro said:

stuff like Fin (m + n) -> Fin (n + m)

You just need to prove that m + n = n + m, and they are the same type.

Mario Carneiro (Jul 30 2022 at 13:39):

you have to be advanced type tetris master to actually come up with a proof of that using FZ and FS

Locria Cyber (Jul 30 2022 at 13:40):

not really

Henrik Böving (Jul 30 2022 at 13:40):

Advanced type tetris master is going in my type theory urban dictionary

Locria Cyber (Jul 30 2022 at 13:40):

Idris has this cast : (a: A) -> (A = B) -> B

Mario Carneiro (Jul 30 2022 at 13:40):

You can prove it using cast but then you don't know e.g. how the value computes on successor

Locria Cyber (Jul 30 2022 at 13:41):

It's literally the same type though

Mario Carneiro (Jul 30 2022 at 13:41):

you won't be able to apply equation lemmas for other recursive definitions

Locria Cyber (Jul 30 2022 at 13:41):

what's equation lemma

Mario Carneiro (Jul 30 2022 at 13:41):

we usually call this DTT hell

Mario Carneiro (Jul 30 2022 at 13:42):

equation lemmas are the definitional equalities that follow from a definition by pattern matching

Locria Cyber (Jul 30 2022 at 13:42):

I've been avoiding using tactics because I don't quite understand the magic.

Locria Cyber (Jul 30 2022 at 13:42):

You can say that I'm a type tetris master

Mario Carneiro (Jul 30 2022 at 13:43):

The advantage of the structure definition of Fin is that you can do all the "real" reasoning on a non-dependent type, namely Nat

Mario Carneiro (Jul 30 2022 at 13:43):

Yes, this style of programming you are using is seen mostly in idris and agda

Henrik Böving (Jul 30 2022 at 13:43):

Locria Cyber said:

I've been avoiding using tactics because I don't quite understand the magic.

I'm afraid that won't really get you too far in the Lean eco system, we are pretty focused on tactics for non trivial term level proofs

Mario Carneiro (Jul 30 2022 at 13:45):

The situation with vectors is pretty similar BTW. In lean 4 they aren't defined, but the lean 3 definition of Vector A n is {l : List A // l.length = n}

Mario Carneiro (Jul 30 2022 at 13:45):

so all the vector operations are just list operations tupled with a proof that they preserve lengths

Mario Carneiro (Jul 30 2022 at 13:46):

and you don't have any problems with e.g. associativity of vector append

Henrik Böving (Jul 30 2022 at 13:46):

This also makes the runtime representation nicer right? With the indexed variant each node is also carrying the rest of the length around

Mario Carneiro (Jul 30 2022 at 13:47):

Indeed

Mario Carneiro (Jul 30 2022 at 13:47):

I think agda has a mechanism to avoid this using ghost arguments

Mario Carneiro (Jul 30 2022 at 13:47):

not sure about idris

Locria Cyber (Jul 30 2022 at 13:47):

Idris has beta reduction for Nat-like and (i forgot the name) for List-like

Locria Cyber (Jul 30 2022 at 13:48):

(runtime representation)

Locria Cyber (Jul 30 2022 at 13:48):

It doesn't have the Array type in Lean, because its List is just as fast

Mario Carneiro (Jul 30 2022 at 13:49):

in lean 4 the improvement of runtime representation for Fin is even more stark. the FZ/FS representation is a unary linked list, while the structure over Nat is a zero-cost wrapper around a GMP bignum with a direct numeral representation for numbers less than I think 2^63

Locria Cyber (Jul 30 2022 at 13:49):

Idris compile to scheme, so it's different

Henrik Böving (Jul 30 2022 at 13:49):

Locria Cyber said:

It doesn't have the Array type in Lean, because its List is just as fast

How can a linked list be just as fast as a slice of memory?

Locria Cyber (Jul 30 2022 at 13:49):

scheme magic?

Mario Carneiro (Jul 30 2022 at 13:49):

does it have O(1) push?

Mario Carneiro (Jul 30 2022 at 13:50):

push to the end

Locria Cyber (Jul 30 2022 at 13:50):

never tried

Locria Cyber (Jul 30 2022 at 13:51):

need to check Chez Scheme's source code to know

Mario Carneiro (Jul 30 2022 at 13:51):

a google search turns up https://www.idris-lang.org/docs/idris2/current/contrib_docs/docs/Data.Linear.Array.html

Locria Cyber (Jul 30 2022 at 13:52):

that's a type class

Locria Cyber (Jul 30 2022 at 13:52):

interface

Mario Carneiro (Jul 30 2022 at 13:52):

there's a data right after

Locria Cyber (Jul 30 2022 at 13:52):

that's in contrib (akin to mathlib4)

Mario Carneiro (Jul 30 2022 at 13:53):

okay, is that a disqualification?

Henrik Böving (Jul 30 2022 at 13:53):

They seem to have a lot of array thingies below

Mario Carneiro (Jul 30 2022 at 13:53):

there's no push though

Locria Cyber (Jul 30 2022 at 13:54):

it's probably incomplete (again, things in contrib are like that)

Locria Cyber (Jul 30 2022 at 13:54):

https://idris2-quickdocs.surge.sh/

Locria Cyber (Jul 30 2022 at 13:55):

Even third-party packages are better than contrib. contrib is the historical artifact before Idris2 core team decided it's a bad idea to let anything in the main repo.

Mario Carneiro (Jul 30 2022 at 13:55):

I would be generally doubtful that a fully functional List type is going to get array performance "by magic"

Locria Cyber (Jul 30 2022 at 13:55):

idk
I assume that list operation in LISP is fast enough

Mario Carneiro (Jul 30 2022 at 13:55):

It's a linked list

Henrik Böving (Jul 30 2022 at 13:56):

But that's not how memory works, as soon as you have a linked list cache performance sucks

Locria Cyber (Jul 30 2022 at 13:56):

probably not in memory

Mario Carneiro (Jul 30 2022 at 13:56):

no, it really is

Locria Cyber (Jul 30 2022 at 13:56):

Do you think that popular scheme implementations would only use linked list (in C)?

Mario Carneiro (Jul 30 2022 at 13:56):

you can sometimes optimize it to be a linked list of arrays but there are lots of operations that will break up the arrays

Mario Carneiro (Jul 30 2022 at 13:57):

(I know because I've written an optimized lisp interpreter)

Locria Cyber (Jul 30 2022 at 13:57):

Idris can't compile to C good enough yet.

Locria Cyber (Jul 30 2022 at 13:57):

The mature backends are Scheme/Racket/Javascript

Mario Carneiro (Jul 30 2022 at 13:58):

Scheme has an actual vector type though

Mario Carneiro (Jul 30 2022 at 13:58):

lists are lists and arrays are arrays in scheme

Locria Cyber (Jul 30 2022 at 13:58):

yes

Mario Carneiro (Jul 30 2022 at 13:58):

pretty sure racket does too

Mario Carneiro (Jul 30 2022 at 13:58):

and javascript has a whole zoo

Mario Carneiro (Jul 30 2022 at 13:59):

so I don't see how a language with only one List type is going to be able to lower this to both lists and arrays

Locria Cyber (Jul 30 2022 at 14:00):

not both

Locria Cyber (Jul 30 2022 at 14:00):

it's mapped to Scheme's list

Mario Carneiro (Jul 30 2022 at 14:00):

which is why I don't think you will get O(1) push with idris List

Locria Cyber (Jul 30 2022 at 14:04):

Maybe not

Locria Cyber (Jul 30 2022 at 14:07):

Locria Cyber said:

Idris has this cast : (a: A) -> (A = B) -> B

How do you do something like this (in Lean)?

Henrik Böving (Jul 30 2022 at 14:19):

You just do it: docs4#cast


Last updated: Dec 20 2023 at 11:08 UTC