diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+# 3.0.2.0
+
+  * Fix list indexing
+  * Remove `foldTwo` from the Jacinda prelude
+  * Add `head#, `tail#`, `init#`, `last#`, `drop#`, `take#` for lists
+
 # 3.0.1.1
 
   * Fix bug with tuples in implicit contexts.
diff --git a/examples/liblibversion.jac b/examples/liblibversion.jac
--- a/examples/liblibversion.jac
+++ b/examples/liblibversion.jac
@@ -1,5 +1,3 @@
 @include'lib/string.jac'
 
-{. TODO: handle type-equality-1-b4033320810f291878747510666a8cf89d0b44830502670dc4d3746b158afa8
-
 unlines¨{% /-lHS/}{captures `0 1 /-lHS([A-Aa-z][A-Za-z0-9\-]*\d+(\.\d+)*)/}
diff --git a/examples/tags.jac b/examples/tags.jac
--- a/examples/tags.jac
+++ b/examples/tags.jac
@@ -1,10 +1,9 @@
-fn mkEx(s) :=
-  '/^' + s + '$/;';
-
-fn processStr(s) :=
+fn processStr(l) :=
   let
+    val s := l->1
     val line := split s /[ \(:]+/
-    val outLine := sprintf '%s\t%s\t%s' (line.3 . fp . mkEx s)
+    val col := #line.1 + 1
+    val outLine := sprintf '%s\t%s\tcall cursor(%i,%i)' (line.2 . fp . l->2 . col)
   in outLine end;
 
-processStr¨{%/fn +[[:lower:]][[:latin:]]*.*:=/}{`0}
+processStr¨{%/fn +[[:lower:]][[:latin:]]*.*:=/}{(`0 . ix)}
diff --git a/jacinda.cabal b/jacinda.cabal
--- a/jacinda.cabal
+++ b/jacinda.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.2
 name:               jacinda
-version:            3.0.1.1
+version:            3.0.2.0
 license:            AGPL-3.0-only
 license-file:       COPYING
 maintainer:         vamchale@gmail.com
diff --git a/man/ja.1 b/man/ja.1
--- a/man/ja.1
+++ b/man/ja.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 3.1.13
+.\" Automatically generated by Pandoc 3.2
 .\"
 .TH "ja (1)" "" "" "" ""
 .SH NAME
@@ -193,6 +193,15 @@
 \f[B]<pattern>,,<pattern> <expr>\f[R] Bookend a stream
 .PP
 \f[B] $> \f[R] Print stream and summary result
+.TP
+\f[B]head#, last#\f[R]
+List a \-> a
+.TP
+\f[B]tail#, init#\f[R]
+List a \-> List a
+.TP
+\f[B]drop#, take#\f[R]
+Int \-> List a \-> List a
 .SS DECLARATIONS
 \f[B]:set fs=/REGEX/;\f[R] Set field separator
 .PP
diff --git a/prelude/fn.jac b/prelude/fn.jac
--- a/prelude/fn.jac
+++ b/prelude/fn.jac
@@ -30,9 +30,3 @@
 
 fn head :=
   ([[:x]|>);
-
-{. fold two on the same stream
-fn foldTwo(op0, op1, seed0, seed1, stream) :=
-  let
-    val go := \acc. \line. (op0 (acc->1) line . op1 (acc->2) line)
-  in go|(seed0.seed1) stream end;
diff --git a/src/A.hs b/src/A.hs
--- a/src/A.hs
+++ b/src/A.hs
@@ -98,6 +98,7 @@
          | Dedup | CatMaybes
          | Negate
          | TallyList -- length of vector
+         | Head | Tail | Init | Last
          deriving (Eq)
 
 instance Pretty BUn where
@@ -116,6 +117,10 @@
     pretty CatMaybes  = ".?"
     pretty Negate     = "-."
     pretty TallyList  = "#*"
+    pretty Head       = "head#"
+    pretty Tail       = "tail#"
+    pretty Init       = "init#"
+    pretty Last       = "last#"
 
 data BTer = ZipW
           | Fold | Scan
@@ -135,7 +140,7 @@
     pretty AllCaptures = "captures"
     pretty Sub1        = "sub1"
     pretty Subs        = "subs"
-    pretty Bookend     = "bookend"
+    pretty Bookend     = ",,"
 
 -- builtin
 data BBin = Plus | Times | Div
@@ -151,6 +156,7 @@
           | Filter | Fold1
           | Match | Sprintf
           | Report
+          | Take | Drop
           deriving (Eq)
 
 instance Pretty BBin where
@@ -162,6 +168,7 @@
     pretty Split = "split"; pretty Splitc = "splitc"; pretty Sprintf = "sprintf"
     pretty Match = "match"; pretty MapMaybe = ":?"; pretty Fold1 = "|>"
     pretty Exp = "**"; pretty DedupOn = "~.*"; pretty Report = "$>"
+    pretty Take = "take#"; pretty Drop = "drop#"
 
 data DfnVar = X | Y deriving (Eq)
 
diff --git a/src/Jacinda/Backend/T.hs b/src/Jacinda/Backend/T.hs
--- a/src/Jacinda/Backend/T.hs
+++ b/src/Jacinda/Backend/T.hs
@@ -363,7 +363,25 @@
 (EApp _ (EApp _ (BB _ NotMatches) s) r) @> b = do
     se <- s@>b; re <- r@>b
     pure (mkB (not$isMatch' (asR re) (asS se)))
+(EApp ty (EApp _ (BB _ Take) n) x) @> b = do
+    n' <- asI<$>(n@>b); x' <- asV<$>(x@>b)
+    pure $ Arr ty (V.take (fromIntegral n') x')
+(EApp ty (EApp _ (BB _ Drop) n) x) @> b = do
+    n' <- asI<$>(n@>b); x' <- asV<$>(x@>b)
+    pure $ Arr ty (V.drop (fromIntegral n') x')
 (Tup ty es) @> b = Tup ty.foldSeq <$> traverse (@>b) es
+(EApp _ (UB _ Head) x) @> b = do
+    x' <- x@>b
+    pure $ V.head (asV x')
+(EApp ty (UB _ Tail) x) @> b = do
+    x' <- x@>b
+    pure $ Arr ty (V.tail (asV x'))
+(EApp _ (UB _ Last) x) @> b = do
+    x' <- x@>b
+    pure $ V.last (asV x')
+(EApp ty (UB _ Init) x) @> b = do
+    x' <- x@>b
+    pure $ Arr ty (V.init (asV x'))
 (EApp _ (UB _ Tally) e) @> b = do
     e' <- e@>b
     let r=fromIntegral (BS.length$asS e')
@@ -395,7 +413,7 @@
 (EApp _ (UB _ IParse) x) @> b = do {x' <- x@>b; pure (parseAsEInt (asS x'))}
 (EApp (TyB TyI) (UB _ Parse) x) @> b = do {x' <- x@>b; pure (parseAsEInt (asS x'))}
 (EApp (TyB TyFloat) (UB _ Parse) x) @> b = do {x' <- x@>b; pure (parseAsF (asS x'))}
-(EApp _ (UB _ (At i)) v) @> b = do {v' <- v@>b; pure (asV v' `at` (i-1))}
+(EApp _ (UB _ (At i)) v) @> b = do {v' <- v@>b; pure (asV v' `at` i)}
 (EApp _ (UB _ (Select i)) x) @> b = do {x' <- x@>b; pure (asT x' !! (i-1))}
 (EApp _ (UB _ Floor) x) @> b = mkI.floor.asF<$>(x@>b)
 (EApp _ (UB _ Ceiling) x) @> b = mkI.ceiling.asF<$>(x@>b)
diff --git a/src/L.x b/src/L.x
--- a/src/L.x
+++ b/src/L.x
@@ -176,6 +176,12 @@
         scan                     { mkBuiltin BuiltinScan }
         "sub1"                   { mkBuiltin BuiltinSub1 }
         subs                     { mkBuiltin BuiltinSubs }
+        "head#"                  { mkBuiltin BuiltinHead }
+        "tail#"                  { mkBuiltin BuiltinTail }
+        "last#"                  { mkBuiltin BuiltinLast }
+        "init#"                  { mkBuiltin BuiltinInit }
+        "take#"                  { mkBuiltin BuiltinTake }
+        "drop#"                  { mkBuiltin BuiltinDrop }
 
         ":i"                     { mkBuiltin BuiltinIParse }
         ":f"                     { mkBuiltin BuiltinFParse }
@@ -418,6 +424,9 @@
              | BuiltinFold | BuiltinFold1
              | BuiltinScan
              | BuiltinSub1 | BuiltinSubs
+             | BuiltinHead | BuiltinTail
+             | BuiltinInit | BuiltinLast
+             | BuiltinDrop | BuiltinTake
 
 instance Pretty Builtin where
     pretty BuiltinIParse   = ":i"
@@ -442,6 +451,12 @@
     pretty BuiltinScan     = "scan"
     pretty BuiltinSub1     = "sub1"
     pretty BuiltinSubs     = "subs"
+    pretty BuiltinHead     = "head#"
+    pretty BuiltinTail     = "tail#"
+    pretty BuiltinInit     = "init#"
+    pretty BuiltinLast     = "last#"
+    pretty BuiltinTake     = "take#"
+    pretty BuiltinDrop     = "drop#"
 
 data Token a = EOF { loc :: a }
              | TokSym { loc :: a, _sym :: Sym }
diff --git a/src/Parser.y b/src/Parser.y
--- a/src/Parser.y
+++ b/src/Parser.y
@@ -156,6 +156,13 @@
     fold1L { TokBuiltin $$ BuiltinFold1 }
     scanL { TokBuiltin $$ BuiltinScan }
 
+    head { TokBuiltin $$ BuiltinHead }
+    tail { TokBuiltin $$ BuiltinTail }
+    init { TokBuiltin $$ BuiltinInit }
+    last { TokBuiltin $$ BuiltinLast }
+    take { TokBuiltin $$ BuiltinTake }
+    drop { TokBuiltin $$ BuiltinDrop }
+
     iParse { TokBuiltin $$ BuiltinIParse }
     fParse { TokBuiltin $$ BuiltinFParse }
 
@@ -304,8 +311,8 @@
   | x { ResVar $1 X }
   | y { ResVar $1 Y }
   | rr { RegexLit (loc $1) (encodeUtf8 $ rr $1) }
-  | min { BB $1 Min }
-  | max { BB $1 Max }
+  | min { BB $1 Min } | max { BB $1 Max }
+  | drop { BB $1 Drop } | take { BB $1 Take }
   | mapMaybeL { RwB $1 MapMaybe }
   | dedupOnL { RwB $1 DedupOn }
   | filterL { RwB $1 Filter }
@@ -323,11 +330,12 @@
   | captures { TB $1 AllCaptures }
   | floor { UB $1 Floor }
   | ceil { UB $1 Ceiling }
-  | floorSym { UB $1 Floor }
-  | ceilSym { UB $1 Ceiling }
+  | floorSym { UB $1 Floor } | ceilSym { UB $1 Ceiling }
   | dedup { UB $1 Dedup }
   | some { UB $1 Some }
   | catMaybes { UB $1 CatMaybes }
+  | head {UB $1 Head} | tail {UB $1 Tail}
+  | last {UB $1 Last} | init {UB $1 Init}
   | neg { UB $1 Negate }
   | ix { NB $1 Ix }
   | z { NB $1 MZ }
diff --git a/src/Parser/Rw.hs b/src/Parser/Rw.hs
--- a/src/Parser/Rw.hs
+++ b/src/Parser/Rw.hs
@@ -39,6 +39,8 @@
 mFi Splitc     = Nothing
 mFi Sprintf    = Nothing
 mFi Match      = Nothing
+mFi Drop       = Nothing
+mFi Take       = Nothing
 mFi Prior      = Just 5
 mFi DedupOn    = Just 5
 mFi Report     = Just 4
diff --git a/src/Ty.hs b/src/Ty.hs
--- a/src/Ty.hs
+++ b/src/Ty.hs
@@ -225,10 +225,12 @@
 checkType (TyB TyFloat) (IsPrintf, _)    = pure ()
 checkType (TyB TyI) (IsPrintf, _)        = pure ()
 checkType (TyB TyBool) (IsPrintf, _)     = pure ()
-checkType (TyTup tys) (c@IsPrintf, l)    = traverse_ (`checkType` (c, l)) tys
-checkType (Rho _ rs) (c@IsPrintf, l)     = traverse_ (`checkType` (c, l)) (IM.elems rs)
+checkType (TyTup tys) (c@IsPrintf, l)    | not$any nest tys = traverse_ (`checkType` (c, l)) tys
+checkType (Rho _ rs) (c@IsPrintf, l)     | tys <- IM.elems rs, not$any nest tys = traverse_ (`checkType` (c, l)) tys
 checkType ty (c, l)                      = throwError $ Doesn'tSatisfy l ty c
 
+nest TyTup{}=True; nest Rho{}=True; nest _=False
+
 checkClass :: Ord a
            => IM.IntMap T -- ^ Unification result
            -> Int
@@ -383,6 +385,8 @@
 tyES s (BB _ Matches) = pure (BB (tyStr ~> tyR ~> tyB) Matches, s)
 tyES s (BB _ NotMatches) = pure (BB (tyStr ~> tyR ~> tyB) NotMatches, s)
 tyES s (UB _ Tally) = pure (UB (tyStr ~> tyI) Tally, s)
+tyES s (BB _ Take) = do {a <- var<$>freshN "a"; pure (BB (tyI ~> tyV a ~> tyV a) Take, s)}
+tyES s (BB _ Drop) = do {a <- var<$>freshN "a"; pure (BB (tyI ~> tyV a ~> tyV a) Drop, s)}
 tyES s (BB _ Div) = pure (BB (tyF ~> tyF ~> tyF) Div, s)
 tyES s (UB _ Not) = pure (UB (tyB ~> tyB) Not, s)
 tyES s (BB _ And) = pure (BB (tyB ~> tyB ~> tyB) And, s)
@@ -395,6 +399,10 @@
 tyES s (UB _ FParse) = pure (UB (tyArr tyStr tyF) FParse, s)
 tyES s (UB _ Floor) = pure (UB (tyArr tyF tyI) Floor, s)
 tyES s (UB _ Ceiling) = pure (UB (tyF ~> tyI) Ceiling, s)
+tyES s (UB _ Head) = do {a <- var<$>freshN "a"; pure (UB (tyV a ~> a) Head, s)}
+tyES s (UB _ Tail) = do {a <- var<$>freshN "a"; pure (UB (tyV a ~> tyV a) Tail, s)}
+tyES s (UB _ Last) = do {a <- var<$>freshN "a"; pure (UB (tyV a ~> a) Last, s)}
+tyES s (UB _ Init) = do {a <- var<$>freshN "a"; pure (UB (tyV a ~> tyV a) Init, s)}
 tyES s (BB _ Report) = do {a <- var <$> freshN "a"; b <- var <$> freshN "b"; pure (BB (tyStream a ~> b ~> TyB TyUnit) Report, s)}
 tyES s (UB _ TallyList) = do {a <- var <$> freshN "a"; pure (UB (a ~> tyI) TallyList, s)}
 tyES s (UB l Negate) = do {a <- freshN "a"; modify (mapCV (addC a (IsNum, l))); let a'=var a in pure (UB (tyArr a' a') Negate, s)}
