///|
pub(open) trait Slice: Length {
  op_as_view(Self, start~ : Int, end~ : Int) -> Self
}

///|
pub impl[Z] Slice for FixedArray[Z] with op_as_view(self, start~, end~) {
  FixedArray::from_iter(self.iter()[start:end])
}

// pub impl[Z] Slice for Iter[Z] with op_as_view(self, start~, end~) {
//   self[start:end]
// }

///|
pub impl[Z] Slice for Array[Z] with op_as_view(self, start~, end~) {
  Array::from_iter(self.iter()[start:end])
}

///|
pub impl Slice for String with op_as_view(self, start~, end~) {
  self.substring(start~, end~)
}

///|
pub fn[Z : Slice] slice(a : Z, start : Int, end : Int) -> Z {
  Z::op_as_view(a, start~, end~)
}

///|
pub fn[Z : Slice] slice_start(a : Z, start : Int) -> Z {
  Z::op_as_view(a, start~, end=Z::length(a))
}