Generic Slice Type Classes #
This file defines type classes for slicing operations on collections, inspired by Python's slice notation. The notation provides three operations:
v⟦:m⟧takes the firstmelements (viaSliceLT)v⟦m:⟧drops the firstmelements (viaSliceGE)v⟦m₁:m₂⟧takes elements from indexm₁tom₂ - 1(viaSlice)
Each notation also supports manual proof syntax with 'h:
v⟦:m⟧'hfor explicit proof inSliceLTv⟦m:⟧'hfor explicit proof inSliceGEv⟦m₁:m₂⟧'hfor explicit proof inSlice
The design follows the pattern of GetElem from the standard library, with:
outParamannotations for better type inference- Validity predicates that can be automatically proven by tactics like
omega - Dependent types where the result collection type can depend on all parameters
Type Classes #
SliceLT: For "take first n elements" operationsSliceGE: For "drop first n elements" operationsSlice: For "range slice" operations
The type classes are generic and can be implemented for any collection type. This file provides instances for:
- Fin tuples: Available in
Starlib.Data.Fin.Tuple.Notation(with proof obligations) - Array: With
Truevalidity (no proof obligations needed) - List: With
Truevalidity (no proof obligations needed)
Sliceable type classes #
Type class for "take first n elements" operations: v⟦:m⟧
We allow for the final subcollection type subcoll to depend on all prior parameters: the
collection type coll, the stop index type stop, the validity predicate valid.
- sliceLT (xs : coll) (stop : stop) (h : valid xs stop) : subcoll xs stop h
Instances
Type class for "drop first n elements" operations: v⟦m:⟧
We allow for the final subcollection type subcoll to depend on all prior parameters: the
collection type coll, the start index type start, the validity predicate valid.
- sliceGE (xs : coll) (start : start) (h : valid xs start) : subcoll xs start h
Instances
Type class for "slice range" operations: v⟦m₁:m₂⟧
We allow for the final subcollection type subcoll to depend on all prior parameters: the
collection type coll, the start index type start, the stop index type stop, the
validity predicate valid.
- slice (xs : coll) (start : start) (stop : stop) (h : valid xs start stop) : subcoll xs start stop h
Instances
Slice notation #
Note: currently we use get_elem_tactic to automatically prove the validity of the indices.
We should switch to a more tailored tactic in the future.
Notation v⟦:stop⟧ for taking the first stop elements
(indexed from 0 to stop - 1) of a collection, assuming the validity for stop can be
automatically proven
Instances For
Notation v⟦:stop⟧'h for taking the first stop elements
(indexed from 0 to stop - 1) with explicit proof
Instances For
Notation v⟦start:⟧ for dropping the first start elements of a collection, assuming the
validity for start can be automatically proven
Instances For
Notation v⟦start:⟧'h for dropping the first start elements with explicit proof
Instances For
Notation v⟦start:stop⟧ for taking elements from index start to stop - 1
(e.g., v⟦1:3⟧ = v[1] ++ v[2]), with range proofs automatically synthesized
Instances For
Notation v⟦start:stop⟧'h for taking elements from index start to stop - 1
(e.g., v⟦1:3⟧ = ![v 1, v 2]), with explicit proof
Instances For
Unexpander for slice notation #
We provide unexpanders to display slice operations in their slice notation form in goal states and error messages, providing a better user experience.
Unexpander for SliceLT.sliceLT to display as v⟦:stop⟧
Instances For
Unexpander for SliceGE.sliceGE to display as v⟦start:⟧
Instances For
Unexpander for Slice.slice to display as v⟦start:stop⟧
Instances For
Instances for Array #
Arrays support slice notation with no proof obligations since Array operations handle boundary cases gracefully (e.g., taking more elements than exist returns the whole array).
Instances for List #
Lists support slice notation with no proof obligations since List operations handle boundary cases gracefully (e.g., taking more elements than exist returns the whole list).