diff --git a/knead.cabal b/knead.cabal
--- a/knead.cabal
+++ b/knead.cabal
@@ -1,10 +1,10 @@
 Name:             knead
-Version:          0.5
+Version:          1.0
 License:          BSD3
 License-File:     LICENSE
 Author:           Henning Thielemann <haskell@henning-thielemann.de>
 Maintainer:       Henning Thielemann <haskell@henning-thielemann.de>
-Homepage:         http://hub.darcs.net/thielema/knead/
+Homepage:         https://hub.darcs.net/thielema/knead/
 Category:         Data Structures
 Synopsis:         Repa-like array processing using LLVM JIT
 Description:
@@ -43,39 +43,40 @@
   .
   The name of the package is inspired by the visualization of typical operations
   like reshaping, collapsing a dimension and extruding another one.
-Tested-With:      GHC==7.4.2, GHC==7.8.4
-Tested-With:      GHC==8.4.3, GHC==8.6.1
-Cabal-Version:    >=1.8
+Tested-With:      GHC==8.4.4, GHC==8.6.5, GHC==8.10.7
+Tested-With:      GHC==9.0.2, GHC==9.2.8, GHC==9.4.6
+Cabal-Version:    >=1.10
 Build-Type:       Simple
 Extra-Source-Files:
   Makefile
 
 Source-Repository this
-  Tag:         0.5
+  Tag:         1.0
   Type:        darcs
-  Location:    http://hub.darcs.net/thielema/knead/
+  Location:    https://hub.darcs.net/thielema/knead/
 
 Source-Repository head
   Type:        darcs
-  Location:    http://hub.darcs.net/thielema/knead/
+  Location:    https://hub.darcs.net/thielema/knead/
 
 Library
   Build-Depends:
-    llvm-dsl >=0.0 && <0.1,
-    llvm-extra >=0.10 && <0.11,
-    llvm-tf >=9.2 && <9.3,
+    llvm-dsl >=0.1 && <0.2,
+    llvm-extra >=0.11 && <0.12,
+    llvm-tf >=9.2 && <13.0,
     tfp >=1.0 && <1.1,
-    comfort-array >=0.3 && <0.5,
+    comfort-array >=0.5 && <0.6,
     fixed-length >=0.2.1 && <0.3,
     storable-record >=0.0.5 && <0.1,
     storable-enum >=0.0 && <0.1,
     bool8 >=0.0 && <0.1,
-    transformers >=0.3 && <0.6,
+    transformers >=0.3 && <0.7,
     tagged >=0.7 && <0.9,
     utility-ht >=0.0.15 && <0.1,
     prelude-compat >=0.0 && <0.0.1,
     base >=4 && <5
 
+  Default-Language: Haskell98
   GHC-Options:      -Wall
   Hs-Source-Dirs:   src
   Exposed-Modules:
@@ -83,22 +84,21 @@
     Data.Array.Knead.Shape.Cubic
     Data.Array.Knead.Shape.Cubic.Int
     Data.Array.Knead.Expression
-    Data.Array.Knead.Expression.Vector
-    Data.Array.Knead.Parameter
-    Data.Array.Knead.Simple.Symbolic
-    Data.Array.Knead.Simple.ShapeDependent
-    Data.Array.Knead.Simple.Physical
-    Data.Array.Knead.Simple.Slice
-    Data.Array.Knead.Simple.Fold
-    Data.Array.Knead.Parameterized.Symbolic
-    Data.Array.Knead.Parameterized.Physical
-    Data.Array.Knead.Parameterized.Slice
-    Data.Array.Knead.Parameterized.Render
+    Data.Array.Knead.Symbolic
+    Data.Array.Knead.Symbolic.ShapeDependent
+    Data.Array.Knead.Symbolic.Physical
+    Data.Array.Knead.Symbolic.Slice
+    Data.Array.Knead.Symbolic.Fold
+    Data.Array.Knead.Symbolic.Render
   Other-Modules:
-    Data.Array.Knead.Simple.Private
-    Data.Array.Knead.Simple.PhysicalPrivate
+    Data.Array.Knead.Parameter
+    Data.Array.Knead.Symbolic.Private
+    Data.Array.Knead.Symbolic.PhysicalPrivate
     Data.Array.Knead.Parameterized.Private
+    Data.Array.Knead.Parameterized.Physical
     Data.Array.Knead.Parameterized.PhysicalHull
+    Data.Array.Knead.Parameterized.Symbolic
+    Data.Array.Knead.Parameterized.Slice
     Data.Array.Knead.Code
     Data.Array.Knead.Shape.Orphan
 
@@ -113,6 +113,7 @@
     tfp,
     utility-ht,
     base
+  Default-Language: Haskell98
   GHC-Options: -Wall
   Hs-Source-Dirs: test
   Main-Is: Main.hs
diff --git a/src/Data/Array/Knead/Code.hs b/src/Data/Array/Knead/Code.hs
--- a/src/Data/Array/Knead/Code.hs
+++ b/src/Data/Array/Knead/Code.hs
@@ -1,10 +1,11 @@
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 module Data.Array.Knead.Code where
 
 import qualified Data.Array.Knead.Shape as Shape
 
+import qualified LLVM.Extra.Multi.Value.Storable as Storable
 import qualified LLVM.Extra.Multi.Value as MultiValue
-import qualified LLVM.Extra.Storable as Storable
 
 import qualified LLVM.Core as LLVM
 
diff --git a/src/Data/Array/Knead/Expression.hs b/src/Data/Array/Knead/Expression.hs
--- a/src/Data/Array/Knead/Expression.hs
+++ b/src/Data/Array/Knead/Expression.hs
@@ -12,9 +12,9 @@
    unliftM1,
    unliftM2,
    unliftM3,
-   liftTupleM,
-   liftTupleM2,
-   liftTupleM3,
+   liftReprM,
+   liftReprM2,
+   liftReprM3,
    zip,
    zip3,
    zip4,
diff --git a/src/Data/Array/Knead/Expression/Vector.hs b/src/Data/Array/Knead/Expression/Vector.hs
deleted file mode 100644
--- a/src/Data/Array/Knead/Expression/Vector.hs
+++ /dev/null
@@ -1,110 +0,0 @@
-module Data.Array.Knead.Expression.Vector where
-
-import qualified Data.Array.Knead.Expression as Expr
-import Data.Array.Knead.Expression (Exp)
-
-import qualified LLVM.Extra.Multi.Value.Vector as MultiValueVec
-import qualified LLVM.Extra.Multi.Value as MultiValue
-import qualified LLVM.Extra.Multi.Vector as MultiVector
-import qualified LLVM.Core as LLVM
-
-import Prelude hiding (replicate, zip, fst, snd)
-
-
-cons ::
-   (LLVM.Positive n, MultiVector.C a) =>
-   LLVM.Vector n a -> Exp (LLVM.Vector n a)
-cons = Expr.lift0 . MultiValueVec.cons
-
-fst ::
-   (LLVM.Positive n, MultiVector.C a, MultiVector.C b) =>
-   Exp (LLVM.Vector n (a,b)) -> Exp (LLVM.Vector n a)
-fst = Expr.lift1 MultiValueVec.fst
-
-snd ::
-   (LLVM.Positive n, MultiVector.C a, MultiVector.C b) =>
-   Exp (LLVM.Vector n (a,b)) -> Exp (LLVM.Vector n b)
-snd = Expr.lift1 MultiValueVec.snd
-
-swap ::
-   (LLVM.Positive n, MultiVector.C a, MultiVector.C b) =>
-   Exp (LLVM.Vector n (a,b)) -> Exp (LLVM.Vector n (b,a))
-swap = Expr.lift1 MultiValueVec.swap
-
-mapFst ::
-   (Exp (LLVM.Vector n a0) -> Exp (LLVM.Vector n a1)) ->
-   Exp (LLVM.Vector n (a0,b)) -> Exp (LLVM.Vector n (a1,b))
-mapFst f =
-   Expr.liftM
-      (MultiValue.liftM
-         (\(a0,b) -> do
-            MultiValue.Cons a1 <- Expr.unliftM1 f $ MultiValue.Cons a0
-            return (a1,b)))
-
-mapSnd ::
-   (Exp (LLVM.Vector n b0) -> Exp (LLVM.Vector n b1)) ->
-   Exp (LLVM.Vector n (a,b0)) -> Exp (LLVM.Vector n (a,b1))
-mapSnd f =
-   Expr.liftM
-      (MultiValue.liftM
-         (\(a,b0) -> do
-            MultiValue.Cons b1 <- Expr.unliftM1 f $ MultiValue.Cons b0
-            return (a,b1)))
-
-
-fst3 ::
-   (LLVM.Positive n, MultiVector.C a, MultiVector.C b, MultiVector.C c) =>
-   Exp (LLVM.Vector n (a,b,c)) -> Exp (LLVM.Vector n a)
-fst3 = Expr.lift1 MultiValueVec.fst3
-
-snd3 ::
-   (LLVM.Positive n, MultiVector.C a, MultiVector.C b, MultiVector.C c) =>
-   Exp (LLVM.Vector n (a,b,c)) -> Exp (LLVM.Vector n b)
-snd3 = Expr.lift1 MultiValueVec.snd3
-
-thd3 ::
-   (LLVM.Positive n, MultiVector.C a, MultiVector.C b, MultiVector.C c) =>
-   Exp (LLVM.Vector n (a,b,c)) -> Exp (LLVM.Vector n c)
-thd3 = Expr.lift1 MultiValueVec.thd3
-
-
-zip ::
-   (LLVM.Positive n, MultiVector.C a, MultiVector.C b) =>
-   Exp (LLVM.Vector n a) -> Exp (LLVM.Vector n b) ->
-   Exp (LLVM.Vector n (a,b))
-zip = Expr.lift2 MultiValueVec.zip
-
-zip3 ::
-   (LLVM.Positive n, MultiVector.C a, MultiVector.C b, MultiVector.C c) =>
-   Exp (LLVM.Vector n a) -> Exp (LLVM.Vector n b) -> Exp (LLVM.Vector n c) ->
-   Exp (LLVM.Vector n (a,b,c))
-zip3 = Expr.lift3 MultiValueVec.zip3
-
-
-replicate ::
-   (LLVM.Positive n, MultiVector.C a) =>
-   Exp a -> Exp (LLVM.Vector n a)
-replicate = Expr.liftM MultiValueVec.replicate
-
-take ::
-   (LLVM.Positive n, LLVM.Positive m, MultiVector.Select a) =>
-   Exp (LLVM.Vector n a) -> Exp (LLVM.Vector m a)
-take = Expr.liftM MultiValueVec.take
-
-takeRev ::
-   (LLVM.Positive n, LLVM.Positive m, MultiVector.Select a) =>
-   Exp (LLVM.Vector n a) -> Exp (LLVM.Vector m a)
-takeRev = Expr.liftM MultiValueVec.takeRev
-
-
-cmp ::
-   (LLVM.Positive n, MultiVector.Comparison a) =>
-   LLVM.CmpPredicate ->
-   Exp (LLVM.Vector n a) -> Exp (LLVM.Vector n a) -> Exp (LLVM.Vector n Bool)
-cmp ord = Expr.liftM2 (MultiValueVec.cmp ord)
-
-select ::
-   (LLVM.Positive n, MultiVector.Select a) =>
-   Exp (LLVM.Vector n Bool) ->
-   Exp (LLVM.Vector n a) -> Exp (LLVM.Vector n a) -> Exp (LLVM.Vector n a)
-select = Expr.liftM3 MultiValueVec.select
diff --git a/src/Data/Array/Knead/Parameterized/Physical.hs b/src/Data/Array/Knead/Parameterized/Physical.hs
--- a/src/Data/Array/Knead/Parameterized/Physical.hs
+++ b/src/Data/Array/Knead/Parameterized/Physical.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE GADTs #-}
+{-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE ForeignFunctionInterface #-}
 module Data.Array.Knead.Parameterized.Physical (
    Phys.Array,
@@ -18,8 +19,8 @@
 
 import qualified Data.Array.Knead.Parameterized.PhysicalHull as PhysHull
 import qualified Data.Array.Knead.Parameterized.Private as Sym
-import qualified Data.Array.Knead.Simple.Physical as Phys
-import qualified Data.Array.Knead.Simple.Private as Core
+import qualified Data.Array.Knead.Symbolic.Physical as Phys
+import qualified Data.Array.Knead.Symbolic.Private as Core
 import qualified Data.Array.Knead.Shape as Shape
 import qualified Data.Array.Knead.Expression as Expr
 import Data.Array.Knead.Code (getElementPtr)
@@ -30,9 +31,9 @@
 import qualified LLVM.DSL.Execution as Code
 import LLVM.DSL.Expression (Exp, unExp)
 
+import qualified LLVM.Extra.Multi.Value.Storable as Storable
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
 import qualified LLVM.Extra.Multi.Value as MultiValue
-import qualified LLVM.Extra.Storable as Storable
-import qualified LLVM.Extra.Marshal as Marshal
 import qualified LLVM.Extra.Memory as Memory
 
 import qualified LLVM.Core as LLVM
@@ -50,7 +51,7 @@
 
 {-# INLINE feed #-}
 feed ::
-   (Shape.C sh, Marshal.MV sh, Storable.C a) =>
+   (Shape.C sh, Marshal.C sh, Storable.C a) =>
    Param.T p (Phys.Array sh a) -> Sym.Array p sh a
 feed arr =
    Param.withMulti (fmap Array.shape arr) $ \getShape valueShape ->
@@ -59,7 +60,7 @@
          case mapFst valueShape $ MultiValue.unzip p of
             (sh, MultiValue.Cons ptr) ->
                Core.Array (Expr.lift0 sh) $
-                  Storable.loadMultiValue <=< getElementPtr sh ptr)
+                  Storable.load <=< getElementPtr sh ptr)
       (\p ->
          case Array.buffer $ Param.get arr p of
             fptr ->
@@ -86,8 +87,7 @@
          case arr param of
             Core.Array z code ->
                code (Shape.zeroIndex z) >>=
-               flip Storable.storeMultiValue resultPtr
-         LLVM.ret ()
+               flip Storable.store resultPtr
    return $ \p ->
       bracket (create p) (delete . fst) $ \(_ctx, param) ->
       Marshal.with param $ \pptr ->
@@ -97,7 +97,7 @@
    Importer (LLVM.Ptr param -> LLVM.Ptr a -> IO ())
 
 theMarshal ::
-   (Shape.Scalar z, Marshal.C a, MultiValue.C a) =>
+   (Shape.Scalar z, Marshal.C a) =>
    Sym.Array p z a -> IO (p -> IO a)
 theMarshal (Sym.Array arr create delete) = do
    func <-
@@ -109,7 +109,6 @@
             Core.Array z code ->
                code (Shape.zeroIndex z) >>=
                flip Memory.store resultPtr
-         LLVM.ret ()
    return $ \p ->
       bracket (create p) (delete . fst) $ \(_ctx, param) ->
       Marshal.with param $ \pptr ->
@@ -123,7 +122,7 @@
 
 
 renderShape ::
-   (Shape.C sh, Marshal.MV sh,
+   (Shape.C sh, Marshal.C sh,
     Storable.C a, MultiValue.C a) =>
    Sym.Array p sh a -> IO (p -> IO (sh, Shape.Size))
 renderShape (Sym.Array arr create delete) = do
@@ -136,7 +135,7 @@
            Core.Array esh _code -> do
               sh <- unExp esh
               Memory.store sh resultPtr
-              Shape.size sh >>= LLVM.ret
+              Shape.size sh
    return $ \p ->
       bracket (create p) (delete . fst) $ \(_ctx, param) ->
       Marshal.alloca $ \shptr ->
@@ -147,14 +146,14 @@
 
 
 render ::
-   (Shape.C sh, Marshal.MV sh, Storable.C a) =>
+   (Shape.C sh, Marshal.C sh, Storable.C a) =>
    Sym.Array p sh a -> IO (p -> IO (Phys.Array sh a))
 render = PhysHull.render . Sym.arrayHull
 
 
 mapAccumLSimple ::
-   (Shape.C sh, Marshal.MV sh,
-    Shape.C n, Marshal.MV n,
+   (Shape.C sh, Marshal.C sh,
+    Shape.C n, Marshal.C n,
     MultiValue.C acc,
     Storable.C a, MultiValue.C a,
     Storable.C b, MultiValue.C b) =>
@@ -169,8 +168,8 @@
          (Sym.arrayHull arrMap)
 
 foldOuterL ::
-   (Shape.C sh, Marshal.MV sh,
-    Shape.C n, Marshal.MV n,
+   (Shape.C sh, Marshal.C sh,
+    Shape.C n, Marshal.C n,
     Storable.C a, MultiValue.C a) =>
    (Exp a -> Exp b -> Exp a) ->
    Sym.Array p sh a ->
@@ -184,7 +183,7 @@
 
 scatter ::
    (Shape.C sh0, Shape.Index sh0 ~ ix0,
-    Shape.C sh1, Shape.Index sh1 ~ ix1, Marshal.MV sh1,
+    Shape.C sh1, Shape.Index sh1 ~ ix1, Marshal.C sh1,
     Storable.C a, MultiValue.C a) =>
    (Exp a -> Exp a -> Exp a) ->
    Sym.Array p sh1 a ->
@@ -197,7 +196,7 @@
 
 scatterMaybe ::
    (Shape.C sh0, Shape.Index sh0 ~ ix0,
-    Shape.C sh1, Shape.Index sh1 ~ ix1, Marshal.MV sh1,
+    Shape.C sh1, Shape.Index sh1 ~ ix1, Marshal.C sh1,
     Storable.C a, MultiValue.C a) =>
    (Exp a -> Exp a -> Exp a) ->
    Sym.Array p sh1 a ->
@@ -210,7 +209,7 @@
 
 permute ::
    (Shape.C sh0, Shape.Index sh0 ~ ix0,
-    Shape.C sh1, Shape.Index sh1 ~ ix1, Marshal.MV sh1,
+    Shape.C sh1, Shape.Index sh1 ~ ix1, Marshal.C sh1,
     Storable.C a, MultiValue.C a) =>
    (Exp a -> Exp a -> Exp a) ->
    Sym.Array p sh1 a ->
diff --git a/src/Data/Array/Knead/Parameterized/PhysicalHull.hs b/src/Data/Array/Knead/Parameterized/PhysicalHull.hs
--- a/src/Data/Array/Knead/Parameterized/PhysicalHull.hs
+++ b/src/Data/Array/Knead/Parameterized/PhysicalHull.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE GADTs #-}
+{-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE ForeignFunctionInterface #-}
 module Data.Array.Knead.Parameterized.PhysicalHull (
    render,
@@ -23,20 +24,20 @@
    ) where
 
 import qualified Data.Array.Knead.Parameterized.Private as Sym
-import qualified Data.Array.Knead.Simple.PhysicalPrivate as Priv
-import qualified Data.Array.Knead.Simple.Private as Core
+import qualified Data.Array.Knead.Symbolic.PhysicalPrivate as Priv
+import qualified Data.Array.Knead.Symbolic.Private as Core
 import qualified Data.Array.Knead.Shape as Shape
 import qualified Data.Array.Knead.Expression as Expr
-import Data.Array.Knead.Simple.PhysicalPrivate (MarshalPtr)
+import Data.Array.Knead.Symbolic.PhysicalPrivate (MarshalPtr)
 
 import Data.Array.Comfort.Storable.Unchecked (Array(Array))
 
 import qualified LLVM.DSL.Execution as Code
 import LLVM.DSL.Expression (Exp, unExp)
 
+import qualified LLVM.Extra.Multi.Value.Storable as Storable
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
 import qualified LLVM.Extra.Multi.Value as MultiValue
-import qualified LLVM.Extra.Storable as Storable
-import qualified LLVM.Extra.Marshal as Marshal
 import qualified LLVM.Extra.Memory as Memory
 import qualified LLVM.Extra.Arithmetic as A
 
@@ -73,7 +74,7 @@
 An example is 'mapFilter'.
 -}
 materialize ::
-   (Shape.C sh, Marshal.MV sh, Storable.C a) =>
+   (Shape.C sh, Marshal.C sh, Storable.C a) =>
    String ->
    (core -> Exp sh) ->
    (core ->
@@ -89,12 +90,11 @@
             param <- Memory.load paramPtr
             sh <- unExp $ shape $ core param
             Memory.store sh resultPtr
-            Shape.size sh >>= LLVM.ret)
+            Shape.size sh)
          (Code.createFunction callFill "fill" $
           \paramPtr shapePtr bufferPtr -> do
             param <- Memory.load paramPtr
-            fill (core param) shapePtr bufferPtr
-            LLVM.ret ())
+            fill (core param) shapePtr bufferPtr)
 
    return $ \p ->
       bracket (create p) (delete . fst) $ \(_ctx, param) ->
@@ -111,7 +111,7 @@
 
 
 materializeExpArray ::
-   (Shape.C sh, Marshal.MV sh, Storable.C a, Storable.C b) =>
+   (Shape.C sh, Marshal.C sh, Storable.C a, Storable.C b) =>
    String ->
    (core -> Exp sh) ->
    (core ->
@@ -129,12 +129,11 @@
             param <- Memory.load paramPtr
             sh <- unExp $ shape $ core param
             Memory.store sh resultPtr
-            Shape.size sh >>= LLVM.ret)
+            Shape.size sh)
          (Code.createFunction callFillExpArray "fill" $
           \paramPtr finalPtr shapePtr bufferPtr -> do
             param <- Memory.load paramPtr
-            fill (core param) finalPtr shapePtr bufferPtr
-            LLVM.ret ())
+            fill (core param) finalPtr shapePtr bufferPtr)
 
    return $ \p ->
       bracket (create p) (delete . fst) $ \(_ctx, param) ->
@@ -160,8 +159,8 @@
 
 
 materialize2 ::
-   (Shape.C sha, Marshal.MV sha,
-    Shape.C shb, Marshal.MV shb,
+   (Shape.C sha, Marshal.C sha,
+    Shape.C shb, Marshal.C shb,
     Storable.C a, Storable.C b) =>
    String ->
    (core -> Exp (sha,shb)) ->
@@ -183,13 +182,11 @@
             sizeAPtr <- LLVM.bitcast sizesPtr
             flip LLVM.store sizeAPtr =<< Shape.size sha
             sizeBPtr <- A.advanceArrayElementPtr sizeAPtr
-            flip LLVM.store sizeBPtr =<< Shape.size shb
-            LLVM.ret ())
+            flip LLVM.store sizeBPtr =<< Shape.size shb)
          (Code.createFunction callFill2 "fill" $
           \paramPtr shapeAPtr bufferAPtr shapeBPtr bufferBPtr -> do
             param <- Memory.load paramPtr
-            fill (core param) (shapeAPtr, bufferAPtr) (shapeBPtr, bufferBPtr)
-            LLVM.ret ())
+            fill (core param) (shapeAPtr, bufferAPtr) (shapeBPtr, bufferBPtr))
 
    return $ \p ->
       bracket (create p) (delete . fst) $ \(_ctx, param) ->
@@ -209,13 +206,13 @@
 
 
 render ::
-   (Shape.C sh, Shape.Index sh ~ ix, Marshal.MV sh,
+   (Shape.C sh, Shape.Index sh ~ ix, Marshal.C sh,
     Storable.C a) =>
    Sym.Hull p (Core.Array sh a) -> IO (p -> IO (Array sh a))
 render =
    materialize "render" Core.shape
       (\(Core.Array esh code) shapePtr bufferPtr -> do
-         let step ix p = flip Storable.storeNextMultiValue p =<< code ix
+         let step ix p = flip Storable.storeNext p =<< code ix
          sh <- Shape.load esh shapePtr
          void $ Shape.loop step sh bufferPtr)
 
@@ -229,7 +226,7 @@
 
 scatter ::
    (Shape.C sh0, Shape.Index sh0 ~ ix0,
-    Shape.C sh1, Shape.Index sh1 ~ ix1, Marshal.MV sh1,
+    Shape.C sh1, Shape.Index sh1 ~ ix1, Marshal.C sh1,
     Storable.C a) =>
    Sym.Hull p (Scatter sh0 sh1 a) -> IO (p -> IO (Array sh1 a))
 scatter =
@@ -249,7 +246,7 @@
 
 scatterMaybe ::
    (Shape.C sh0, Shape.Index sh0 ~ ix0,
-    Shape.C sh1, Shape.Index sh1 ~ ix1, Marshal.MV sh1,
+    Shape.C sh1, Shape.Index sh1 ~ ix1, Marshal.C sh1,
     Storable.C a) =>
    Sym.Hull p (ScatterMaybe sh0 sh1 a) -> IO (p -> IO (Array sh1 a))
 scatterMaybe =
@@ -267,8 +264,8 @@
    }
 
 mapAccumLSimple ::
-   (Shape.C sh, Marshal.MV sh,
-    Shape.C n, Marshal.MV n,
+   (Shape.C sh, Marshal.C sh,
+    Shape.C n, Marshal.C n,
     MultiValue.C acc, Storable.C a, Storable.C b) =>
    Sym.Hull p (MapAccumLSimple sh n acc a b) -> IO (p -> IO (Array (sh,n) b))
 mapAccumLSimple =
@@ -288,7 +285,7 @@
 
 -- FIXME: check correct size of array of initial values
 mapAccumLSequence ::
-   (Shape.C n, Marshal.MV n, MultiValue.C acc,
+   (Shape.C n, Marshal.C n, MultiValue.C acc,
     Storable.C final, MultiValue.C final,
     Storable.C a, Storable.C b) =>
    Sym.Hull p (MapAccumLSequence n acc final a b) ->
@@ -310,8 +307,8 @@
 
 -- FIXME: check correct size of array of initial values
 mapAccumL ::
-   (Shape.C sh, Marshal.MV sh,
-    Shape.C n, Marshal.MV n,
+   (Shape.C sh, Marshal.C sh,
+    Shape.C n, Marshal.C n,
     MultiValue.C acc,
     Storable.C final, MultiValue.C final,
     Storable.C a, Storable.C b) =>
@@ -336,8 +333,8 @@
 
 -- FIXME: check correct size of array of initial values
 foldOuterL ::
-   (Shape.C n, Marshal.MV n,
-    Shape.C sh, Marshal.MV sh,
+   (Shape.C n, Marshal.C n,
+    Shape.C sh, Marshal.C sh,
     Storable.C a) =>
    Sym.Hull p (FoldOuterL n sh a b) -> IO (p -> IO (Array sh a))
 foldOuterL =
@@ -354,7 +351,7 @@
    }
 
 mapFilter ::
-   (Shape.Sequence n, Marshal.MV n, Storable.C b) =>
+   (Shape.Sequence n, Marshal.C n, Storable.C b) =>
    Sym.Hull p (MapFilter n a b) -> IO (p -> IO (Array n b))
 mapFilter =
    materialize "mapFilter"
@@ -372,8 +369,8 @@
 
 -- FIXME: check correct size of row selection array
 filterOuter ::
-   (Shape.Sequence n, Marshal.MV n,
-    Shape.C sh, Marshal.MV sh,
+   (Shape.Sequence n, Marshal.C n,
+    Shape.C sh, Marshal.C sh,
     Storable.C a) =>
    Sym.Hull p (FilterOuter n sh a) -> IO (p -> IO (Array (n,sh) a))
 filterOuter =
@@ -392,8 +389,8 @@
    }
 
 addDimension ::
-   (Shape.C sh, Marshal.MV sh,
-    Shape.C n, Marshal.MV n,
+   (Shape.C sh, Marshal.C sh,
+    Shape.C n, Marshal.C n,
     Storable.C b) =>
    Sym.Hull p (AddDimension sh n a b) -> IO (p -> IO (Array (sh,n) b))
 addDimension =
diff --git a/src/Data/Array/Knead/Parameterized/Private.hs b/src/Data/Array/Knead/Parameterized/Private.hs
--- a/src/Data/Array/Knead/Parameterized/Private.hs
+++ b/src/Data/Array/Knead/Parameterized/Private.hs
@@ -1,8 +1,9 @@
 {-# LANGUAGE ExistentialQuantification #-}
-{-# LANGUAGE GADTs #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 module Data.Array.Knead.Parameterized.Private where
 
-import qualified Data.Array.Knead.Simple.Symbolic as Core
+import qualified Data.Array.Knead.Symbolic as Core
 
 import qualified Data.Array.Knead.Shape as Shape
 import qualified Data.Array.Knead.Expression as Expr
@@ -10,8 +11,8 @@
 
 import qualified LLVM.DSL.Parameter as Param
 
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
 import qualified LLVM.Extra.Multi.Value as MultiValue
-import qualified LLVM.Extra.Marshal as Marshal
 
 import Control.Monad (liftM2)
 import Control.Applicative (Applicative (pure, (<*>)), )
@@ -26,7 +27,7 @@
 -- in principle we could define Array in terms of Hull and Core.Array
 data Array p sh a =
    forall parameter context.
-   (Marshal.MV parameter) =>
+   (Marshal.C parameter) =>
    Array {
       core :: MultiValue.T parameter -> Core.Array sh a,
       createContext :: p -> IO (context, parameter),
@@ -45,7 +46,7 @@
 
 
 (!) ::
-   (Shape.C sh, Shape.Index sh ~ ix, Marshal.MV ix,
+   (Shape.C sh, Shape.Index sh ~ ix, Marshal.C ix,
     Shape.Scalar z) =>
    Array p sh a -> Param.T p ix -> Array p z a
 (!) arr pix =
@@ -57,7 +58,7 @@
 
 
 fill ::
-   (Shape.C sh, Marshal.MV sh, Marshal.MV a) =>
+   (Shape.C sh, Marshal.C sh, Marshal.C a) =>
    Param.T p sh -> Param.T p a -> Array p sh a
 fill sh a =
    Shape.paramWith sh $ \getSh valueSh ->
@@ -78,7 +79,7 @@
 
 
 id ::
-   (Shape.C sh, Marshal.MV sh, Shape.Index sh ~ ix) =>
+   (Shape.C sh, Marshal.C sh, Shape.Index sh ~ ix) =>
    Param.T p sh -> Array p sh ix
 id sh =
    Shape.paramWith sh $ \getSh valueSh ->
@@ -88,32 +89,32 @@
       deletePlain
 
 map ::
-   (Shape.C sh, Marshal.MV c) =>
+   (Shape.C sh, Marshal.C c) =>
    (Exp c -> Exp a -> Exp b) ->
    Param.T p c -> Array p sh a -> Array p sh b
 map = lift Core.map
 
 mapWithIndex ::
-   (Shape.C sh, Marshal.MV c, Shape.Index sh ~ ix) =>
+   (Shape.C sh, Marshal.C c, Shape.Index sh ~ ix) =>
    (Exp c -> Exp ix -> Exp a -> Exp b) ->
    Param.T p c -> Array p sh a -> Array p sh b
 mapWithIndex = lift Core.mapWithIndex
 
 
 fold1 ::
-   (Shape.C sh0, Shape.C sh1, Marshal.MV c, MultiValue.C a) =>
+   (Shape.C sh0, Shape.C sh1, Marshal.C c, MultiValue.C a) =>
    (Exp c -> Exp a -> Exp a -> Exp a) ->
    Param.T p c -> Array p (sh0, sh1) a -> Array p sh0 a
 fold1 = lift Core.fold1
 
 fold1All ::
-   (Shape.C sh, Shape.Scalar z, Marshal.MV c, MultiValue.C a) =>
+   (Shape.C sh, Shape.Scalar z, Marshal.C c, MultiValue.C a) =>
    (Exp c -> Exp a -> Exp a -> Exp a) ->
    Param.T p c -> Array p sh a -> Array p z a
 fold1All = lift (\p -> Core.fill Shape.scalar . Core.fold1All p)
 
 lift ::
-   (Shape.C sh0, Shape.C sh1, Marshal.MV c) =>
+   (Shape.C sh0, Shape.C sh1, Marshal.C c) =>
    (f -> Core.Array sh0 a -> Core.Array sh1 b) ->
    (Exp c -> f) ->
    Param.T p c -> Array p sh0 a -> Array p sh1 b
@@ -127,7 +128,7 @@
 
 data Hull p a =
    forall parameter context.
-   (Marshal.MV parameter) =>
+   (Marshal.C parameter) =>
    Hull {
       hullCore :: MultiValue.T parameter -> a,
       hullCreateContext :: p -> IO (context, parameter),
@@ -182,7 +183,7 @@
 
 
 
-expParam :: (Marshal.MV a) => Param.T p a -> Param.Tunnel p a
+expParam :: (Marshal.C a) => Param.T p a -> Param.Tunnel p a
 expParam = Param.tunnel MultiValue.cons
 
 
diff --git a/src/Data/Array/Knead/Parameterized/Render.hs b/src/Data/Array/Knead/Parameterized/Render.hs
deleted file mode 100644
--- a/src/Data/Array/Knead/Parameterized/Render.hs
+++ /dev/null
@@ -1,200 +0,0 @@
-{-# LANGUAGE TypeFamilies #-}
-{- |
-Simplify running the @render@ function by handling passing of parameters.
--}
-module Data.Array.Knead.Parameterized.Render (
-   run,
-   MarshalExp(..),
-   MapFilter(..),
-   FilterOuter(..),
-   Scatter(..),
-   ScatterMaybe(..),
-   MapAccumLSimple(..),
-   MapAccumLSequence(..),
-   MapAccumL(..),
-   FoldOuterL(..),
-   AddDimension(..),
-   ) where
-
-import qualified Data.Array.Knead.Parameterized.PhysicalHull as PhysHullP
-import qualified Data.Array.Knead.Parameterized.Physical as PhysP
-import qualified Data.Array.Knead.Parameterized.Private as Sym
-import qualified Data.Array.Knead.Simple.Physical as Phys
-import qualified Data.Array.Knead.Simple.Private as Core
-import qualified Data.Array.Knead.Shape as Shape
-import Data.Array.Knead.Parameterized.PhysicalHull
-         (MapFilter, FilterOuter,
-          MapAccumLSimple, MapAccumLSequence, MapAccumL, FoldOuterL,
-          Scatter, ScatterMaybe, AddDimension)
-import Data.Array.Knead.Expression (Exp, )
-
-import qualified LLVM.DSL.Parameter as Param
-
-import qualified LLVM.Extra.Multi.Value as MultiValue
-import qualified LLVM.Extra.Storable as Storable
-import qualified LLVM.Extra.Marshal as Marshal
-
-import Control.Arrow (arr, )
-import Control.Applicative (liftA2, liftA3, pure, (<*>), )
-
-import Data.Tuple.HT (fst3, snd3, thd3, )
-
-import Prelude2010
-import Prelude ()
-
-
-
-class C f where
-   type Plain f
-   build :: Sym.Hull p f -> IO (p -> Plain f)
-
-instance
-   (Marshal.MV sh, Shape.C sh, Storable.C a) =>
-      C (Core.Array sh a) where
-   type Plain (Core.Array sh a) = IO (Phys.Array sh a)
-   build = PhysHullP.render
-
-instance
-   (Shape.Sequence n, Marshal.MV n,
-    Storable.C b, MultiValue.C b) =>
-      C (MapFilter n a b) where
-   type Plain (MapFilter n a b) = IO (Phys.Array n b)
-   build = PhysHullP.mapFilter
-
-instance
-   (Shape.Sequence n, Marshal.MV n,
-    Shape.C sh, Marshal.MV sh,
-    Storable.C a, MultiValue.C a) =>
-      C (FilterOuter n sh a) where
-   type Plain (FilterOuter n sh a) = IO (Phys.Array (n,sh) a)
-   build = PhysHullP.filterOuter
-
-instance
-   (Shape.C sh0, Marshal.MV sh0,
-    Shape.C sh1, Marshal.MV sh1,
-    Storable.C a, MultiValue.C a) =>
-      C (Scatter sh0 sh1 a) where
-   type Plain (Scatter sh0 sh1 a) = IO (Phys.Array sh1 a)
-   build = PhysHullP.scatter
-
-instance
-   (Shape.C sh0, Marshal.MV sh0,
-    Shape.C sh1, Marshal.MV sh1,
-    Storable.C a, MultiValue.C a) =>
-      C (ScatterMaybe sh0 sh1 a) where
-   type Plain (ScatterMaybe sh0 sh1 a) = IO (Phys.Array sh1 a)
-   build = PhysHullP.scatterMaybe
-
-instance
-   (Shape.C sh, Marshal.MV sh,
-    Shape.C n, Marshal.MV n,
-    MultiValue.C acc,
-    Storable.C a, MultiValue.C a,
-    Storable.C b, MultiValue.C b) =>
-      C (MapAccumLSimple sh n acc a b) where
-   type Plain (MapAccumLSimple sh n acc a b) = IO (Phys.Array (sh,n) b)
-   build = PhysHullP.mapAccumLSimple
-
-instance
-   (Shape.C n, Marshal.MV n,
-    MultiValue.C acc,
-    Storable.C final, MultiValue.C final,
-    Storable.C a, MultiValue.C a,
-    Storable.C b, MultiValue.C b) =>
-      C (MapAccumLSequence n acc final a b) where
-   type Plain (MapAccumLSequence n acc final a b) = IO (final, Phys.Array n b)
-   build = PhysHullP.mapAccumLSequence
-
-instance
-   (Shape.C sh, Marshal.MV sh,
-    Shape.C n, Marshal.MV n,
-    MultiValue.C acc,
-    Storable.C final, MultiValue.C final,
-    Storable.C a, MultiValue.C a,
-    Storable.C b, MultiValue.C b) =>
-      C (MapAccumL sh n acc final a b) where
-   type Plain (MapAccumL sh n acc final a b) =
-            IO (Phys.Array sh final, Phys.Array (sh,n) b)
-   build = PhysHullP.mapAccumL
-
-instance
-   (Shape.C n, Marshal.MV n,
-    Shape.C sh, Marshal.MV sh,
-    Storable.C a, MultiValue.C a,
-    Storable.C b, MultiValue.C b) =>
-      C (FoldOuterL n sh a b) where
-   type Plain (FoldOuterL n sh a b) = IO (Phys.Array sh a)
-   build = PhysHullP.foldOuterL
-
-instance
-   (Shape.C sh, Marshal.MV sh,
-    Shape.C n, Marshal.MV n,
-    Storable.C b, MultiValue.C b) =>
-      C (AddDimension sh n a b) where
-   type Plain (AddDimension sh n a b) = IO (Phys.Array (sh,n) b)
-   build = PhysHullP.addDimension
-
-
-singleton :: Exp a -> Core.Array () a
-singleton = Core.fromScalar
-
-instance (Storable.C a, MultiValue.C a) => C (Exp a) where
-   type Plain (Exp a) = IO a
-   build = PhysP.the . Sym.runHull . fmap singleton
-
-newtype MarshalExp a = MarshalExp {getMarshalExp :: Exp a}
-
-instance (Marshal.C a, MultiValue.C a) => C (MarshalExp a) where
-   type Plain (MarshalExp a) = IO a
-   build = PhysP.theMarshal . Sym.runHull . fmap (singleton . getMarshalExp)
-
-instance (Argument arg, C func) => C (arg -> func) where
-   type Plain (arg -> func) = PlainArg arg -> Plain func
-   build f = fmap curry $ build $ Sym.extendHull fst f <*> buildArg (arr snd)
-
-
-class Argument arg where
-   type PlainArg arg
-   buildArg :: Param.T p (PlainArg arg) -> Sym.Hull p arg
-
-instance
-   (Shape.C sh, Marshal.MV sh, Storable.C a) =>
-      Argument (Core.Array sh a) where
-   type PlainArg (Core.Array sh a) = Phys.Array sh a
-   buildArg = Sym.arrayHull . PhysP.feed
-
-instance (Marshal.MV a) => Argument (Exp a) where
-   type PlainArg (Exp a) = a
-   buildArg = Sym.expHull . Sym.expParam
-
-instance (Argument a, Argument b) => Argument (a,b) where
-   type PlainArg (a,b) = (PlainArg a, PlainArg b)
-   buildArg p = liftA2 (,) (buildArg $ fmap fst p) (buildArg $ fmap snd p)
-
-instance (Argument a, Argument b, Argument c) => Argument (a,b,c) where
-   type PlainArg (a,b,c) = (PlainArg a, PlainArg b, PlainArg c)
-   buildArg p =
-      liftA3 (,,)
-         (buildArg $ fmap fst3 p) (buildArg $ fmap snd3 p) (buildArg $ fmap thd3 p)
-
-
-run :: (C f) => f -> IO (Plain f)
-run f = fmap ($()) $ build $ pure f
-
-
-
-_example ::
-   (Marshal.MV x,
-    Shape.C sha, Marshal.MV sha, Storable.C a,
-    Shape.C shb, Marshal.MV shb, Storable.C b,
-    Shape.C shc, Marshal.MV shc, Storable.C c) =>
-   (Exp x -> Core.Array sha a -> Core.Array shb b -> Core.Array shc c) ->
-   IO (x -> Phys.Array sha a -> Phys.Array shb b -> IO (Phys.Array shc c))
-_example f =
-   fmap (\g -> curry $ curry g) $
-   PhysP.render $
-   Sym.runHull $
-   pure f
-      <*> Sym.expHull (Sym.expParam $ arr (fst.fst))
-      <*> Sym.arrayHull (PhysP.feed $ arr (snd.fst))
-      <*> Sym.arrayHull (PhysP.feed $ arr snd)
diff --git a/src/Data/Array/Knead/Parameterized/Slice.hs b/src/Data/Array/Knead/Parameterized/Slice.hs
--- a/src/Data/Array/Knead/Parameterized/Slice.hs
+++ b/src/Data/Array/Knead/Parameterized/Slice.hs
@@ -14,8 +14,8 @@
 import qualified Data.Array.Knead.Parameterized.Private as Priv
 import Data.Array.Knead.Parameterized.Private (Array(Array), )
 
-import qualified Data.Array.Knead.Simple.Slice as Slice
-import qualified Data.Array.Knead.Simple.Private as Core
+import qualified Data.Array.Knead.Symbolic.Slice as Slice
+import qualified Data.Array.Knead.Symbolic.Private as Core
 
 import qualified Data.Array.Knead.Shape.Cubic.Int as Index
 import qualified Data.Array.Knead.Shape.Cubic as Cubic
@@ -25,8 +25,8 @@
 
 import qualified LLVM.DSL.Parameter as Param
 
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
 import qualified LLVM.Extra.Multi.Value as MultiValue
-import qualified LLVM.Extra.Marshal as Marshal
 
 import qualified Type.Data.Num.Unary as Unary
 
@@ -37,7 +37,7 @@
 -}
 data T p sh0 sh1 =
    forall parameter context.
-   (Marshal.MV parameter) =>
+   (Marshal.C parameter) =>
    Cons {
       _core :: MultiValue.T parameter -> Slice.T sh0 sh1,
       _createContext :: p -> IO (context, parameter),
@@ -85,7 +85,7 @@
 extrude = lift Slice.extrude
 
 lift ::
-   (Marshal.MV i) =>
+   (Marshal.C i) =>
    (Exp i -> Slice.Cubic rank0 rank1 -> Slice.Cubic rank2 rank3) ->
    Param.T p i ->
    Cubic p rank0 rank1 -> Cubic p rank2 rank3
diff --git a/src/Data/Array/Knead/Parameterized/Symbolic.hs b/src/Data/Array/Knead/Parameterized/Symbolic.hs
--- a/src/Data/Array/Knead/Parameterized/Symbolic.hs
+++ b/src/Data/Array/Knead/Parameterized/Symbolic.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE Rank2Types #-}
 {-# LANGUAGE GADTs #-}
+{-# LANGUAGE TypeOperators #-}
 module Data.Array.Knead.Parameterized.Symbolic (
    Array,
    Exp,
@@ -19,7 +20,7 @@
    ) where
 
 import qualified Data.Array.Knead.Parameterized.Private as Sym
-import qualified Data.Array.Knead.Simple.Symbolic as Core
+import qualified Data.Array.Knead.Symbolic as Core
 import Data.Array.Knead.Parameterized.Private (Array, gather, )
 
 import qualified Data.Array.Knead.Shape as Shape
@@ -28,8 +29,8 @@
 
 import qualified LLVM.DSL.Parameter as Param
 
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
 import qualified LLVM.Extra.Multi.Value as MultiValue
-import qualified LLVM.Extra.Marshal as Marshal
 
 import Control.Applicative ((<*>), )
 
@@ -46,7 +47,7 @@
 
 backpermute ::
    (Shape.C sh0, Shape.Index sh0 ~ ix0,
-    Shape.C sh1, Shape.Index sh1 ~ ix1, Marshal.MV sh1,
+    Shape.C sh1, Shape.Index sh1 ~ ix1, Marshal.C sh1,
     MultiValue.C a) =>
    Param.T p sh1 ->
    (Exp ix1 -> Exp ix0) ->
@@ -56,7 +57,7 @@
 
 
 zipWith ::
-   (Shape.C sh, Marshal.MV d) =>
+   (Shape.C sh, Marshal.C d) =>
    (Exp d -> Exp a -> Exp b -> Exp c) ->
    Param.T p d -> Array p sh a -> Array p sh b -> Array p sh c
 zipWith f d a b =
@@ -64,14 +65,14 @@
 
 
 withExp ::
-   (Marshal.MV x) =>
+   (Marshal.C x) =>
    (Exp x -> Core.Array shb b -> Core.Array sha a) ->
    Param.T p x -> Array p shb b -> Array p sha a
 withExp f x =
    Sym.runHull . Sym.mapHullWithExp f (Sym.expParam x) . Sym.arrayHull
 
 withExp2 ::
-   (Marshal.MV x) =>
+   (Marshal.C x) =>
    (Exp x -> Core.Array sha a -> Core.Array shb b -> Core.Array shc c) ->
    Param.T p x -> Array p sha a -> Array p shb b -> Array p shc c
 withExp2 f x a b =
@@ -80,7 +81,7 @@
      <*> Sym.arrayHull b
 
 withExp3 ::
-   (Marshal.MV x) =>
+   (Marshal.C x) =>
    (Exp x -> Core.Array sha a ->
     Core.Array shb b -> Core.Array shc c -> Core.Array shd d) ->
    Param.T p x -> Array p sha a ->
diff --git a/src/Data/Array/Knead/Shape.hs b/src/Data/Array/Knead/Shape.hs
--- a/src/Data/Array/Knead/Shape.hs
+++ b/src/Data/Array/Knead/Shape.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE UndecidableInstances #-}
@@ -15,6 +16,8 @@
 
    Range(Range), range, rangeFrom, rangeTo,
    Shifted(Shifted), shifted, shiftedOffset, shiftedSize,
+   Cyclic(Cyclic), cyclic, cyclicSize,
+
    Enumeration(Enumeration), EnumBounded(..),
 
    Scalar(..),
@@ -23,22 +26,22 @@
 
 import qualified Data.Array.Knead.Expression as Expr
 import Data.Array.Knead.Shape.Orphan
-         (zeroBased, zeroBasedSize,
+         (zeroBased, zeroBasedSize, cyclic, cyclicSize,
           singletonRange, unzipRange, singletonShifted, unzipShifted)
 import Data.Array.Knead.Expression (Exp, )
 
 import qualified Data.Array.Comfort.Shape as Shape
 import Data.Array.Comfort.Shape
-         (Index, ZeroBased, Range(Range), Shifted(Shifted),
+         (Index, ZeroBased, Range(Range), Shifted(Shifted), Cyclic,
           Enumeration(Enumeration))
 import Data.Ix (Ix)
 
 import qualified LLVM.DSL.Parameter as Param
 
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
 import qualified LLVM.Extra.Multi.Value as MultiValue
 import qualified LLVM.Extra.Multi.Iterator as IterMV
 import qualified LLVM.Extra.Tuple as Tuple
-import qualified LLVM.Extra.Marshal as Marshal
 import qualified LLVM.Extra.Memory as Memory
 import qualified LLVM.Extra.Iterator as Iter
 import qualified LLVM.Extra.ScalarOrVector as SoV
@@ -66,10 +69,10 @@
 value = Expr.lift0 . MultiValue.cons
 
 paramWith ::
-   (Marshal.MV b) =>
+   (Marshal.C b) =>
    Param.T p b ->
    (forall parameters.
-    (Marshal.MV parameters) =>
+    (Marshal.C parameters) =>
     (p -> parameters) ->
     (forall val. (Expr.Value val) =>
      MultiValue.T parameters -> val b) ->
@@ -79,7 +82,7 @@
    Param.withMulti p (\get val -> f get (Expr.lift0 . val))
 
 load ::
-   (Marshal.MV sh) =>
+   (Marshal.C sh) =>
    f sh -> LLVM.Value (LLVM.Ptr (Marshal.Struct sh)) ->
    LLVM.CodeGenFunction r (MultiValue.T sh)
 load _ = Memory.load
@@ -91,7 +94,7 @@
    (C sh) =>
    MultiValue.T sh -> MultiValue.T (Index sh) ->
    LLVM.CodeGenFunction r (LLVM.Value Size)
-offset sh ix = ($ix) . snd =<< sizeOffset sh
+offset sh ix = ($ ix) . snd =<< sizeOffset sh
 
 class (MultiValue.C sh, MultiValue.C (Index sh), Shape.Indexed sh) => C sh where
    {-
@@ -261,13 +264,24 @@
             IterMV.take len $ Iter.iterate MultiValue.inc from
 
 
+instance
+      (Integral n, ToSize n, MultiValue.Comparison n) => C (Cyclic n) where
+   intersectCode sha shb =
+      cyclic <$> MultiValue.min (cyclicSize sha) (cyclicSize shb)
+   size = toSize . cyclicSize
+   sizeOffset sh = Monad.lift2 (,) (toSize $ cyclicSize sh) (return toSize)
+   iterator sh =
+      IterMV.take (cyclicSize sh) $
+      Iter.iterate MultiValue.inc MultiValue.zero
+
+
 class (IterMV.Enum enum, MultiValue.Bounded enum) => EnumBounded enum where
    enumOffset :: MultiValue.T enum -> LLVM.CodeGenFunction r (LLVM.Value Size)
 
 instance
    (ToSize w, MultiValue.Additive w,
     LLVM.IsInteger w, SoV.IntegerConstant w, Num w,
-    Tuple.ValueOf w ~ LLVM.Value w,
+    MultiValue.Repr w ~ LLVM.Value w,
     LLVM.CmpRet w, LLVM.IsPrimitive w,
     Enum e, Bounded e) =>
       EnumBounded (Enum.T w e) where
diff --git a/src/Data/Array/Knead/Shape/Cubic.hs b/src/Data/Array/Knead/Shape/Cubic.hs
--- a/src/Data/Array/Knead/Shape/Cubic.hs
+++ b/src/Data/Array/Knead/Shape/Cubic.hs
@@ -31,9 +31,9 @@
 
 import qualified LLVM.DSL.Parameter as Param
 
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
 import qualified LLVM.Extra.Multi.Value as MultiValue
 import qualified LLVM.Extra.Multi.Iterator as IterMV
-import qualified LLVM.Extra.Marshal as Marshal
 import qualified LLVM.Extra.Iterator as Iter
 import qualified LLVM.Extra.Arithmetic as A
 import qualified LLVM.Extra.Tuple as Tuple
@@ -76,7 +76,7 @@
     Dec.Natural (Dec.FromUnary rank Dec.:*: LLVM.SizeOf Shape.Size)) =>
    Param.T p (T tag rank) ->
    (forall parameters.
-    (Marshal.MV parameters) =>
+    (Marshal.C parameters) =>
     (p -> parameters) ->
     (forall val. (Expr.Value val) =>
      MultiValue.T parameters -> val (T tag rank)) ->
@@ -207,19 +207,9 @@
 toFixedList :: (Unary.Natural n) => [a] -> FixedLength.T n a
 toFixedList xs = snd $ Trav.mapAccumL (\(y:ys) () -> (ys,y)) xs (pure ())
 
-instance
-   (Unary.Natural rank,
-    Dec.Natural (Dec.FromUnary rank),
-    Dec.Natural (Dec.FromUnary rank Dec.:*: LLVM.SizeOf Shape.Size)) =>
-      Marshal.MV (T tag rank) where
 
-
-instance (Unary.Natural rank) => Tuple.Value (T tag rank) where
-   type ValueOf (T tag rank) = FixedLength.T rank (Tuple.ValueOf Index.Int)
-   valueOf = fmap Tuple.valueOf . decons
-
-
 instance (Unary.Natural rank) => MultiValue.C (T tag rank) where
+   type Repr (T tag rank) = FixedLength.T rank (MultiValue.Repr Index.Int)
    cons = MultiValue.Cons . fmap (\(Index.Int i) -> LLVM.valueOf i) . decons
    undef = constant $ MultiValue.undef
    zero = constant $ MultiValue.zero
@@ -248,9 +238,12 @@
       Fold.and $
       FixedLength.zipWith ComfortShape.inBounds
          (shapeFromInt <$> sh) (indexFromInt <$> ix)
-   offset (Cons sh) (Cons ix) =
-      Fold.foldl'
-         (\off (s,i) -> off * ComfortShape.size s + fromIntegral i) 0 $
+   unifiedOffset (Cons sh) (Cons ix) =
+      Fold.foldlM
+         (\off (s,i) -> do
+            ioff <- ComfortShape.unifiedOffset s i
+            return $! off * ComfortShape.size s + ioff)
+         0 $
       FixedLength.zipWith (,) (shapeFromInt <$> sh) (indexFromInt <$> ix)
 
 shapeFromInt :: Index.Int -> ZeroBased Shape.Size
diff --git a/src/Data/Array/Knead/Shape/Cubic/Int.hs b/src/Data/Array/Knead/Shape/Cubic/Int.hs
--- a/src/Data/Array/Knead/Shape/Cubic/Int.hs
+++ b/src/Data/Array/Knead/Shape/Cubic/Int.hs
@@ -6,9 +6,8 @@
 
 import qualified Data.Array.Knead.Expression as Expr
 
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
 import qualified LLVM.Extra.Multi.Value as MultiValue
-import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Tuple as Tuple
 import qualified LLVM.Extra.Arithmetic as A
 
 import qualified LLVM.Core as LLVM
@@ -34,11 +33,8 @@
    switchSingle x = x
 
 
-instance Tuple.Value Int where
-   type ValueOf Int = LLVM.Value Word
-   valueOf (Int x) = LLVM.valueOf x
-
 instance MultiValue.C Int where
+   type Repr Int = LLVM.Value Word
    cons (Int x) = MultiValue.consPrimitive x
    undef = MultiValue.undefPrimitive
    zero = MultiValue.zeroPrimitive
@@ -69,5 +65,3 @@
 instance Marshal.C Int where
    pack (Int i) = i
    unpack = Int
-
-instance Marshal.MV Int where
diff --git a/src/Data/Array/Knead/Shape/Orphan.hs b/src/Data/Array/Knead/Shape/Orphan.hs
--- a/src/Data/Array/Knead/Shape/Orphan.hs
+++ b/src/Data/Array/Knead/Shape/Orphan.hs
@@ -7,10 +7,11 @@
 import qualified Data.Array.Comfort.Shape as Shape
 import Data.Array.Comfort.Shape
          (ZeroBased(ZeroBased), Range(Range), Shifted(Shifted),
+          Cyclic(Cyclic),
           Enumeration(Enumeration))
 
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
 import qualified LLVM.Extra.Multi.Value as MultiValue
-import qualified LLVM.Extra.Marshal as Marshal
 import qualified LLVM.Extra.Memory as Memory
 import qualified LLVM.Extra.Tuple as Tuple
 
@@ -43,6 +44,7 @@
    valueOf (ZeroBased n) = ZeroBased $ Tuple.valueOf n
 
 instance (MultiValue.C n) => MultiValue.C (ZeroBased n) where
+   type Repr (ZeroBased n) = ZeroBased (MultiValue.Repr n)
    cons (ZeroBased n) = zeroBased (MultiValue.cons n)
    undef = zeroBased MultiValue.undef
    zero = zeroBased MultiValue.zero
@@ -80,10 +82,8 @@
    pack = Marshal.pack . Shape.zeroBasedSize
    unpack = Shape.ZeroBased . Marshal.unpack
 
-instance (Marshal.MV n) => Marshal.MV (ZeroBased n) where
 
 
-
 singletonRange :: n -> Range n
 singletonRange n = Range n n
 
@@ -103,6 +103,7 @@
    valueOf (Range from to) = Range (Tuple.valueOf from) (Tuple.valueOf to)
 
 instance (MultiValue.C n) => MultiValue.C (Range n) where
+   type Repr (Range n) = Range (MultiValue.Repr n)
    cons (Range from to) = zipRange (MultiValue.cons from) (MultiValue.cons to)
    undef = MultiValue.compose $ singletonRange MultiValue.undef
    zero = MultiValue.compose $ singletonRange MultiValue.zero
@@ -156,6 +157,7 @@
       Shifted (Tuple.valueOf start) (Tuple.valueOf len)
 
 instance (MultiValue.C n) => MultiValue.C (Shifted n) where
+   type Repr (Shifted n) = Shifted (MultiValue.Repr n)
    cons (Shifted start len) =
       zipShifted (MultiValue.cons start) (MultiValue.cons len)
    undef = MultiValue.compose $ singletonShifted MultiValue.undef
@@ -193,11 +195,66 @@
 
 
 
-instance (Enum enum, Bounded enum) => Tuple.Value (Enumeration enum) where
-   type ValueOf (Enumeration enum) = ()
-   valueOf Enumeration = ()
+unzipCyclic :: MultiValue.T (Cyclic n) -> Cyclic (MultiValue.T n)
+unzipCyclic (MultiValue.Cons (Cyclic n)) = Cyclic (MultiValue.Cons n)
 
+cyclicSize :: (Expr.Value val) => val (Cyclic n) -> val n
+cyclicSize = Expr.lift1 $ Shape.cyclicSize . unzipCyclic
+
+cyclic :: (Expr.Value val) => val n -> val (Cyclic n)
+cyclic = Expr.lift1 $ \(MultiValue.Cons n) -> MultiValue.Cons (Cyclic n)
+
+instance (Tuple.Undefined n) => Tuple.Undefined (Cyclic n) where
+   undef = Cyclic Tuple.undef
+
+instance (Tuple.Phi n) => Tuple.Phi (Cyclic n) where
+   phi bb = fmap Cyclic . Tuple.phi bb . Shape.cyclicSize
+   addPhi bb (Shape.Cyclic a) (Shape.Cyclic b) = Tuple.addPhi bb a b
+
+instance (Tuple.Value n) => Tuple.Value (Cyclic n) where
+   type ValueOf (Cyclic n) = Cyclic (Tuple.ValueOf n)
+   valueOf (Cyclic n) = Cyclic $ Tuple.valueOf n
+
+instance (MultiValue.C n) => MultiValue.C (Cyclic n) where
+   type Repr (Cyclic n) = Cyclic (MultiValue.Repr n)
+   cons (Cyclic n) = cyclic (MultiValue.cons n)
+   undef = cyclic MultiValue.undef
+   zero = cyclic MultiValue.zero
+   phi bb = Monad.lift cyclic . MultiValue.phi bb . cyclicSize
+   addPhi bb a b = MultiValue.addPhi bb (cyclicSize a) (cyclicSize b)
+
+type instance
+   MultiValue.Decomposed f (Cyclic pn) = Cyclic (MultiValue.Decomposed f pn)
+type instance
+   MultiValue.PatternTuple (Cyclic pn) = Cyclic (MultiValue.PatternTuple pn)
+
+instance (MultiValue.Compose n) => MultiValue.Compose (Cyclic n) where
+   type Composed (Cyclic n) = Cyclic (MultiValue.Composed n)
+   compose (Cyclic n) = cyclic (MultiValue.compose n)
+
+instance (MultiValue.Decompose pn) => MultiValue.Decompose (Cyclic pn) where
+   decompose (Cyclic p) sh = MultiValue.decompose p <$> unzipCyclic sh
+
+instance (Expr.Compose n) => Expr.Compose (Cyclic n) where
+   type Composed (Cyclic n) = Cyclic (Expr.Composed n)
+   compose (Cyclic n) = Expr.lift1 cyclic (Expr.compose n)
+
+instance (Expr.Decompose pn) => Expr.Decompose (Cyclic pn) where
+   decompose (Cyclic p) = Cyclic . Expr.decompose p . cyclicSize
+
+instance (Memory.C n) => Memory.C (Cyclic n) where
+   type Struct (Cyclic n) = Memory.Struct n
+   compose = Memory.compose . Shape.cyclicSize
+   decompose = fmap Cyclic . Memory.decompose
+
+instance (Marshal.C n) => Marshal.C (Cyclic n) where
+   pack = Marshal.pack . Shape.cyclicSize
+   unpack = Shape.Cyclic . Marshal.unpack
+
+
+
 instance (Enum enum, Bounded enum) => MultiValue.C (Enumeration enum) where
+   type Repr (Enumeration enum) = ()
    cons = MultiValue.consUnit
    undef = MultiValue.undefUnit
    zero = MultiValue.zeroUnit
diff --git a/src/Data/Array/Knead/Simple/Fold.hs b/src/Data/Array/Knead/Simple/Fold.hs
deleted file mode 100644
--- a/src/Data/Array/Knead/Simple/Fold.hs
+++ /dev/null
@@ -1,98 +0,0 @@
-{- |
-Reduce selected dimensions.
-Alternatively you may reorder dimensions with 'ShapeDep.backpermute'
-and fold once along multiple dimensions.
--}
-{-# LANGUAGE GADTs #-}
-{-# LANGUAGE Rank2Types #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE TypeOperators #-}
-module Data.Array.Knead.Simple.Fold (
-   T,
-   Cubic,
-   apply,
-   passAny,
-   pass,
-   fold,
-   (Core.$:.),
-   ) where
-
-import qualified Data.Array.Knead.Simple.Private as Core
-import Data.Array.Knead.Simple.Private (Array(Array), Code, Val, )
-
-import qualified Data.Array.Knead.Shape.Cubic.Int as Index
-import qualified Data.Array.Knead.Shape.Cubic as Cubic
-import qualified Data.Array.Knead.Shape as Shape
-import qualified Data.Array.Knead.Expression as Expr
-import Data.Array.Knead.Shape.Cubic ((#:.), (:.)((:.)), )
-
-import LLVM.DSL.Expression (Exp, unExp)
-
-import qualified LLVM.Extra.Multi.Value as MultiValue
-import LLVM.Extra.Multi.Value (atom, )
-
-import qualified Type.Data.Num.Unary as Unary
-
-import Prelude hiding (zipWith, zipWith3, zip, zip3, replicate, )
-
-
-data T sh0 sh1 a =
-   forall ix0 ix1.
-   (Shape.Index sh0 ~ ix0, Shape.Index sh1 ~ ix1) =>
-   Cons
-      (Exp sh0 -> Exp sh1)
-      (forall r. Val sh0 -> (Val ix0 -> Code r a) -> (Val ix1 -> Code r a))
-
-
-apply ::
-   (Core.C array, Shape.C sh0, Shape.C sh1, MultiValue.C a) =>
-   T sh0 sh1 a ->
-   array sh0 a ->
-   array sh1 a
-apply (Cons fsh reduce) =
-   Core.lift1 $ \(Array sh code) ->
-      Array (fsh sh) (\ix -> do sh0 <- unExp sh; reduce sh0 code ix)
-
-
-type Cubic rank0 rank1 = T (Cubic.Shape rank0) (Cubic.Shape rank1)
-
-passAny :: Cubic rank rank a
-passAny = Cons id (const id)
-
-pass ::
-   (Unary.Natural rank0, Unary.Natural rank1, MultiValue.C a) =>
-   Cubic rank0 rank1 a ->
-   Cubic (Unary.Succ rank0) (Unary.Succ rank1) a
-pass (Cons fsh reduce) =
-   Cons
-      (Expr.modify (atom:.atom) $ \(sh:.s) -> fsh sh :. s)
-      (\sh code ->
-       Cubic.switchR $ \jx j ->
-          reduce (Cubic.tail sh) (\kx -> code (kx #:. j)) jx)
-
-
-fold1CodeLinear ::
-   (Unary.Natural rank, MultiValue.C a) =>
-   (Exp a -> Exp a -> Exp a) ->
-   Exp Index.Int ->
-   (Val (Cubic.Index (Unary.Succ rank)) -> Code r a) ->
-   (Val (Cubic.Index rank) -> Code r a)
-fold1CodeLinear f nc code ix =
-   Core.fold1Code f
-      (Expr.lift1 (MultiValue.compose . Shape.ZeroBased) $ Index.decons nc)
-      (\j -> code (ix #:. Index.cons j))
-
-fold ::
-   (Unary.Natural rank0, Unary.Natural rank1, MultiValue.C a) =>
-   (Exp a -> Exp a -> Exp a) ->
-   Cubic rank0 rank1 a ->
-   Cubic (Unary.Succ rank0) rank1 a
-fold f (Cons fsh reduce) =
-   Cons
-      (fsh . Cubic.tail)
-      (\sh code jx ->
-          reduce (Cubic.tail sh)
-             (fold1CodeLinear f (Expr.lift0 (Cubic.head sh)) code) jx)
-
-
-instance Core.Process (T sh0 sh1 a) where
diff --git a/src/Data/Array/Knead/Simple/Physical.hs b/src/Data/Array/Knead/Simple/Physical.hs
deleted file mode 100644
--- a/src/Data/Array/Knead/Simple/Physical.hs
+++ /dev/null
@@ -1,195 +0,0 @@
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE Rank2Types #-}
-{-# LANGUAGE ForeignFunctionInterface #-}
-module Data.Array.Knead.Simple.Physical (
-   Array,
-   shape,
-   toList,
-   fromList,
-   vectorFromList,
-   with,
-   render,
-   scanl1,
-   mapAccumLSimple,
-   scatter,
-   scatterMaybe,
-   permute,
-   ) where
-
-import qualified Data.Array.Knead.Simple.PhysicalPrivate as Priv
-import qualified Data.Array.Knead.Simple.Private as Sym
-import qualified Data.Array.Knead.Shape as Shape
-import qualified Data.Array.Knead.Expression as Expr
-import Data.Array.Knead.Simple.PhysicalPrivate (MarshalPtr)
-import Data.Array.Knead.Code (getElementPtr)
-
-import qualified LLVM.DSL.Execution as Code
-import LLVM.DSL.Expression (Exp, unExp)
-
-import qualified Data.Array.Comfort.Storable.Mutable.Unchecked as MutArray
-import qualified Data.Array.Comfort.Storable.Unchecked as Array
-import qualified Data.Array.Comfort.Shape as ComfortShape
-import Data.Array.Comfort.Storable.Unchecked (Array(Array))
-
-import qualified LLVM.Extra.Multi.Value as MultiValue
-import qualified LLVM.Extra.Storable as Storable
-import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Memory as Memory
-import qualified LLVM.Extra.Maybe as Maybe
-
-import qualified LLVM.Core as LLVM
-
-import Foreign.Storable (Storable, )
-import Foreign.ForeignPtr (withForeignPtr, mallocForeignPtrArray, )
-import Foreign.Ptr (FunPtr, Ptr, )
-
-import Control.Monad.HT (void, (<=<), )
-import Control.Applicative (liftA2, (<$>), )
-
-import Prelude2010 hiding (scanl1)
-import Prelude ()
-
-
-shape :: Array sh a -> sh
-shape = Array.shape
-
-toList ::
-   (Shape.C sh, Storable a) =>
-   Array sh a -> IO [a]
-toList = MutArray.toList <=< MutArray.unsafeThaw
-
-fromList ::
-   (Shape.C sh, Storable a) =>
-   sh -> [a] -> IO (Array sh a)
-fromList sh = MutArray.unsafeFreeze <=< MutArray.fromList sh
-
-vectorFromList ::
-   (Num n, Storable a) =>
-   [a] -> IO (Array (ComfortShape.ZeroBased n) a)
-vectorFromList xs =
-   Array.mapShape (\(Shape.ZeroBased n) -> Shape.ZeroBased $ fromIntegral n) <$>
-   (MutArray.unsafeFreeze =<< MutArray.vectorFromList xs)
-
-
-{- |
-The symbolic array is only valid inside the enclosed action.
--}
-with ::
-   (Shape.C sh, Storable.C a) =>
-   (Sym.Array sh a -> IO b) ->
-   Array sh a -> IO b
-with f (Array sh fptr) =
-   withForeignPtr fptr $ \ptr ->
-      f $
-      Sym.Array
-         (Shape.value sh)
-         (\ix ->
-            Storable.loadMultiValue =<<
-               getElementPtr (Shape.value sh) (LLVM.valueOf ptr) ix)
-
-
-type Importer f = FunPtr f -> f
-
-foreign import ccall safe "dynamic" callShaper ::
-   Importer (LLVM.Ptr sh -> IO Shape.Size)
-
-foreign import ccall safe "dynamic" callRenderer ::
-   Importer (LLVM.Ptr sh -> Ptr a -> IO ())
-
-
-materialize ::
-   (Shape.C sh, Marshal.MV sh, Storable.C a) =>
-   String ->
-   Exp sh ->
-   (LLVM.Value (MarshalPtr sh) ->
-    LLVM.Value (Ptr a) -> LLVM.CodeGenFunction () ()) ->
-   IO (Array sh a)
-materialize name esh code =
-   Marshal.alloca $ \lshptr -> do
-      (fsh, farr) <-
-         Code.compile name $
-         liftA2 (,)
-            (Code.createFunction callShaper "shape" $ \ptr -> do
-               sh <- unExp esh
-               Memory.store sh ptr
-               Shape.size sh >>= LLVM.ret)
-            (Code.createFunction callRenderer "fill"
-               (\paramPtr arrayPtr -> code paramPtr arrayPtr >> LLVM.ret ()))
-      n <- fsh lshptr
-      fptr <- mallocForeignPtrArray (fromIntegral n)
-      withForeignPtr fptr $ farr lshptr
-      sh <- Marshal.peek lshptr
-      return (Array sh fptr)
-
-render ::
-   (Shape.C sh, Marshal.MV sh, Storable.C a) =>
-   Sym.Array sh a -> IO (Array sh a)
-render (Sym.Array esh code) =
-   materialize "render" esh $ \sptr ptr -> do
-      let step ix p = flip Storable.storeNextMultiValue p =<< code ix
-      sh <- Shape.load esh sptr
-      void $ Shape.loop step sh ptr
-
-scanl1 ::
-   (Shape.C sh, Marshal.MV sh,
-    Shape.C n, Marshal.MV n,
-    Storable.C a, MultiValue.C a) =>
-   (Exp a -> Exp a -> Exp a) ->
-   Sym.Array (sh, n) a -> IO (Array (sh, n) a)
-scanl1 f (Sym.Array esh code) =
-   materialize "scanl1" esh $ \sptr ptr -> do
-      (sh, n) <- MultiValue.unzip <$> Shape.load esh sptr
-      let step ix ptrStart =
-             fmap fst $
-             (\body -> Shape.loop body n (ptrStart, Maybe.nothing)) $
-                   \k0 (ptr0, macc0) -> do
-                a <- code $ MultiValue.zip ix k0
-                acc1 <- Maybe.run macc0 (return a) (flip (Expr.unliftM2 f) a)
-                ptr1 <- Storable.storeNextMultiValue acc1 ptr0
-                return (ptr1, Maybe.just acc1)
-      void $ Shape.loop step sh ptr
-
-mapAccumLSimple ::
-   (Shape.C sh, Marshal.MV sh,
-    Shape.C n, Marshal.MV n,
-    MultiValue.C acc, Storable.C x, Storable.C y) =>
-   (Exp acc -> Exp x -> Exp (acc,y)) ->
-   Sym.Array sh acc -> Sym.Array (sh, n) x -> IO (Array (sh, n) y)
-mapAccumLSimple f arrInit arrData =
-   materialize "mapAccumLSimple" (Sym.shape arrData) $
-      Priv.mapAccumLSimple f arrInit arrData
-
-scatterMaybe ::
-   (Shape.C sh0, Shape.Index sh0 ~ ix0,
-    Shape.C sh1, Shape.Index sh1 ~ ix1, Marshal.MV sh1,
-    Storable.C a) =>
-   (Exp a -> Exp a -> Exp a) ->
-   Sym.Array sh1 a ->
-   Sym.Array sh0 (Maybe (ix1, a)) -> IO (Array sh1 a)
-scatterMaybe accum arrInit arrMap =
-   materialize "scatterMaybe" (Sym.shape arrInit) $
-      Priv.scatterMaybe accum arrInit arrMap
-
-scatter ::
-   (Shape.C sh0, Shape.Index sh0 ~ ix0,
-    Shape.C sh1, Shape.Index sh1 ~ ix1, Marshal.MV sh1,
-    Storable.C a) =>
-   (Exp a -> Exp a -> Exp a) ->
-   Sym.Array sh1 a ->
-   Sym.Array sh0 (ix1, a) -> IO (Array sh1 a)
-scatter accum arrInit arrMap =
-   materialize "scatter" (Sym.shape arrInit) $
-      Priv.scatter accum arrInit arrMap
-
-permute ::
-   (Shape.C sh0, Shape.Index sh0 ~ ix0,
-    Shape.C sh1, Shape.Index sh1 ~ ix1, Marshal.MV sh1,
-    Storable.C a) =>
-   (Exp a -> Exp a -> Exp a) ->
-   Sym.Array sh1 a ->
-   (Exp ix0 -> Exp ix1) ->
-   Sym.Array sh0 a ->
-   IO (Array sh1 a)
-permute accum deflt ixmap input =
-   scatter accum deflt
-      (Sym.mapWithIndex (Expr.lift2 MultiValue.zip . ixmap) input)
diff --git a/src/Data/Array/Knead/Simple/PhysicalPrivate.hs b/src/Data/Array/Knead/Simple/PhysicalPrivate.hs
deleted file mode 100644
--- a/src/Data/Array/Knead/Simple/PhysicalPrivate.hs
+++ /dev/null
@@ -1,258 +0,0 @@
-{-# LANGUAGE TypeFamilies #-}
-module Data.Array.Knead.Simple.PhysicalPrivate where
-
-import qualified Data.Array.Knead.Simple.Private as Sym
-import qualified Data.Array.Knead.Shape as Shape
-import qualified Data.Array.Knead.Expression as Expr
-import Data.Array.Knead.Code (getElementPtr)
-
-import LLVM.DSL.Expression (Exp, unExp)
-
-import qualified LLVM.Extra.Multi.Value as MultiValue
-import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Storable as Storable
-import qualified LLVM.Extra.Control as C
-
-import qualified LLVM.Core as LLVM
-
-import Foreign.Ptr (Ptr, )
-
-import qualified Control.Applicative.HT as App
-import Control.Monad.HT (void, )
-import Control.Applicative ((<$>), )
-
-import Data.Tuple.HT (mapSnd, )
-
-import Prelude2010
-import Prelude ()
-
-
-
-type MarshalPtr a = LLVM.Ptr (Marshal.Struct a)
-
-writeArray ::
-   (Shape.C sh, Shape.Index sh ~ ix, Storable.C a) =>
-   MultiValue.T sh ->
-   (MultiValue.T ix -> LLVM.CodeGenFunction r (MultiValue.T a)) ->
-   LLVM.Value (Ptr a) ->
-   LLVM.CodeGenFunction r (LLVM.Value (Ptr a))
-writeArray sh code ptr = do
-   let clear ix p = flip Storable.storeNextMultiValue p =<< code ix
-   Shape.loop clear sh ptr
-
-
-mapAccumLLoop ::
-   (MultiValue.C acc, Storable.C b,
-    Shape.C sh, Shape.Index sh ~ ix) =>
-   (MultiValue.T ix -> LLVM.CodeGenFunction r (MultiValue.T a)) ->
-   (Exp acc -> Exp a -> Exp (acc, b)) ->
-   MultiValue.T sh ->
-   LLVM.Value (Ptr b) -> MultiValue.T acc ->
-   LLVM.CodeGenFunction r (LLVM.Value (Ptr b), MultiValue.T acc)
-mapAccumLLoop code f n yPtr accInit = do
-   let step k0 (ptr0, acc0) = do
-         x <- code k0
-         (acc1,y) <- MultiValue.unzip <$> Expr.unliftM2 f acc0 x
-         ptr1 <- Storable.storeNextMultiValue y ptr0
-         return (ptr1, acc1)
-   Shape.loop step n (yPtr, accInit)
-
-mapAccumLSimple ::
-   (Shape.C sh, Marshal.MV sh,
-    Shape.C n, Marshal.MV n,
-    MultiValue.C acc,
-    Storable.C x,
-    Storable.C y) =>
-   (Exp acc -> Exp x -> Exp (acc,y)) ->
-   Sym.Array sh acc -> Sym.Array (sh, n) x ->
-   LLVM.Value (MarshalPtr (sh,n)) ->
-   LLVM.Value (Ptr y) ->
-   LLVM.CodeGenFunction r ()
-mapAccumLSimple f (Sym.Array _ initCode) (Sym.Array esh code) sptr ptr = do
-   (sh, n) <- MultiValue.unzip <$> Shape.load esh sptr
-   let step ix ptrStart = do
-         accInit <- initCode ix
-         fst <$> mapAccumLLoop (code . MultiValue.zip ix) f n ptrStart accInit
-   void $ Shape.loop step sh ptr
-
-mapAccumLSequence ::
-   (Shape.C n, Marshal.MV n,
-    MultiValue.C acc, Storable.C final,
-    Storable.C x,
-    Storable.C y) =>
-   (Exp acc -> Exp x -> Exp (acc,y)) ->
-   (Exp acc -> Exp final) ->
-   Exp acc -> Sym.Array n x ->
-   LLVM.Value (Ptr final) ->
-   LLVM.Value (MarshalPtr n) ->
-   LLVM.Value (Ptr y) ->
-   LLVM.CodeGenFunction r ()
-mapAccumLSequence f final initExp (Sym.Array esh code) accPtr sptr yPtr = do
-   n <- Shape.load esh sptr
-   accInit <- unExp initExp
-   accExit <- snd <$> mapAccumLLoop code f n yPtr accInit
-   flip Storable.storeMultiValue accPtr =<< Expr.unliftM1 final accExit
-
-mapAccumL ::
-   (Shape.C sh, Marshal.MV sh,
-    Shape.C n, Marshal.MV n,
-    MultiValue.C acc, Storable.C final,
-    Storable.C x,
-    Storable.C y) =>
-   (Exp acc -> Exp x -> Exp (acc,y)) ->
-   (Exp acc -> Exp final) ->
-   Sym.Array sh acc -> Sym.Array (sh, n) x ->
-   (LLVM.Value (MarshalPtr sh), LLVM.Value (Ptr final)) ->
-   (LLVM.Value (MarshalPtr (sh,n)), LLVM.Value (Ptr y)) ->
-   LLVM.CodeGenFunction r ()
-mapAccumL f final (Sym.Array _ initCode) (Sym.Array esh code)
-      (_, accPtr) (sptr, yPtr) = do
-   (sh, n) <- MultiValue.unzip <$> Shape.load esh sptr
-   let step ix (accPtr0, yPtrStart) = do
-         accInit <- initCode ix
-         (ptrStop, accExit) <-
-            mapAccumLLoop (code . MultiValue.zip ix) f n yPtrStart accInit
-         accPtr1 <-
-            flip Storable.storeNextMultiValue accPtr0
-               =<< Expr.unliftM1 final accExit
-         return (accPtr1, ptrStop)
-   void $ Shape.loop step sh (accPtr,yPtr)
-
-foldOuterL ::
-   (Shape.C sh, Marshal.MV sh,
-    Shape.C n, Marshal.MV n,
-    Storable.C a) =>
-   (Exp a -> Exp b -> Exp a) ->
-   Sym.Array sh a -> Sym.Array (n,sh) b ->
-   LLVM.Value (MarshalPtr sh) ->
-   LLVM.Value (Ptr a) ->
-   LLVM.CodeGenFunction r ()
-foldOuterL f (Sym.Array _ initCode) (Sym.Array esh code) sptr ptr = do
-   sh <- Shape.load (Expr.snd esh) sptr
-   n <- MultiValue.fst <$> unExp esh
-   void $ writeArray sh initCode ptr
-
-   let step k ix ptr0 = do
-         b <- code $ MultiValue.zip k ix
-         a0 <- Storable.loadMultiValue ptr0
-         a1 <- Expr.unliftM2 f a0 b
-         Storable.storeNextMultiValue a1 ptr0
-   void $ Shape.loop (\k () -> void $ Shape.loop (step k) sh ptr) n ()
-
-{- |
-We need a scalar Shape type @n@.
-Scalar Shape types could be distinguished from other Shape types
-by the fact that you can convert any Index into a Shape.
--}
-mapFilter ::
-   (Shape.Sequence n, Marshal.MV n,
-    Storable.C b) =>
-   (Exp a -> Exp b) ->
-   (Exp a -> Exp Bool) ->
-   Sym.Array n a ->
-   LLVM.Value (MarshalPtr n) ->
-   LLVM.Value (Ptr b) ->
-   LLVM.CodeGenFunction r (MultiValue.T n)
-mapFilter f p (Sym.Array esh code) sptr ptr = do
-   n <- Shape.load esh sptr
-   let step ix (dstPtr,dstIx) = do
-         a <- code ix
-         MultiValue.Cons c <- Expr.unliftM1 p a
-         C.ifThen c (dstPtr,dstIx)
-            (App.lift2 (,)
-               (flip Storable.storeNextMultiValue dstPtr =<< Expr.unliftM1 f a)
-               (MultiValue.inc dstIx))
-   Shape.sequenceShapeFromIndex . snd
-      =<< Shape.loop step n (ptr, MultiValue.zero)
-
-filterOuter ::
-   (Shape.Sequence n, Marshal.MV n,
-    Shape.C sh, Marshal.MV sh,
-    Storable.C a) =>
-   Sym.Array n Bool ->
-   Sym.Array (n,sh) a ->
-   LLVM.Value (MarshalPtr (n,sh)) ->
-   LLVM.Value (Ptr a) ->
-   LLVM.CodeGenFunction r (MultiValue.T (n,sh))
-filterOuter (Sym.Array _eish selectCode) (Sym.Array esh code) sptr ptr = do
-   (n,sh) <- MultiValue.unzip <$> Shape.load esh sptr
-   let step k (dstPtr0,dstK) = do
-         MultiValue.Cons c <- selectCode k
-         C.ifThen c (dstPtr0,dstK)
-            (do
-               dstPtr1 <- writeArray sh (code . MultiValue.zip k) dstPtr0
-               (,) dstPtr1 <$> MultiValue.inc dstK)
-   finalN <-
-      Shape.sequenceShapeFromIndex . snd
-         =<< Shape.loop step n (ptr, MultiValue.zero)
-   return $ MultiValue.zip finalN sh
-
-
-scatterMaybe ::
-   (Shape.C sh0, Shape.Index sh0 ~ ix0,
-    Shape.C sh1, Shape.Index sh1 ~ ix1,
-    Marshal.MV sh1,
-    Storable.C a) =>
-   (Exp a -> Exp a -> Exp a) ->
-   Sym.Array sh1 a -> Sym.Array sh0 (Maybe (ix1, a)) ->
-   LLVM.Value (MarshalPtr sh1) ->
-   LLVM.Value (Ptr a) ->
-   LLVM.CodeGenFunction r ()
-scatterMaybe accum (Sym.Array esh codeInit) (Sym.Array eish codeMap)
-      sptr ptr = do
-
-   sh <- Shape.load esh sptr
-   void $ writeArray sh codeInit ptr
-
-   ish <- unExp eish
-   let fill ix () = do
-         (MultiValue.Cons c, (jx, a)) <-
-            mapSnd MultiValue.unzip . MultiValue.splitMaybe <$> codeMap ix
-         C.ifThen c () $ do
-            p <- getElementPtr sh ptr jx
-            flip Storable.storeMultiValue p
-               =<< Expr.unliftM2 (flip accum) a
-               =<< Storable.loadMultiValue p
-   Shape.loop fill ish ()
-
-scatter ::
-   (Shape.C sh0, Shape.Index sh0 ~ ix0,
-    Shape.C sh1, Shape.Index sh1 ~ ix1,
-    Marshal.MV sh1,
-    Storable.C a) =>
-   (Exp a -> Exp a -> Exp a) ->
-   Sym.Array sh1 a ->
-   Sym.Array sh0 (Shape.Index sh1, a) ->
-   LLVM.Value (MarshalPtr sh1) ->
-   LLVM.Value (Ptr a) ->
-   LLVM.CodeGenFunction r ()
-scatter accum (Sym.Array esh codeInit) (Sym.Array eish codeMap) sptr ptr = do
-   sh <- Shape.load esh sptr
-   void $ writeArray sh codeInit ptr
-
-   ish <- unExp eish
-   let fill ix () = do
-         (jx, a) <- MultiValue.unzip <$> codeMap ix
-         p <- getElementPtr sh ptr jx
-         flip Storable.storeMultiValue p
-            =<< Expr.unliftM2 (flip accum) a
-            =<< Storable.loadMultiValue p
-   Shape.loop fill ish ()
-
-addDimension ::
-   (Shape.C n, Marshal.MV n, Shape.Index n ~ k,
-    Shape.C sh, Marshal.MV sh,
-    Storable.C b) =>
-   Exp n ->
-   (Exp k -> Exp a -> Exp b) ->
-   Sym.Array sh a ->
-   LLVM.Value (MarshalPtr (sh,n)) ->
-   LLVM.Value (Ptr b) ->
-   LLVM.CodeGenFunction r ()
-addDimension en select (Sym.Array esh code) sptr ptr = do
-   (sh,n) <- MultiValue.unzip <$> Shape.load (Expr.zip esh en) sptr
-
-   let fill ix ptr0 = do
-         a <- code ix
-         writeArray n (\k -> Expr.unliftM2 select k a) ptr0
-   void $ Shape.loop fill sh ptr
diff --git a/src/Data/Array/Knead/Simple/Private.hs b/src/Data/Array/Knead/Simple/Private.hs
deleted file mode 100644
--- a/src/Data/Array/Knead/Simple/Private.hs
+++ /dev/null
@@ -1,203 +0,0 @@
-{-# LANGUAGE Rank2Types #-}
-{-# LANGUAGE TypeFamilies #-}
-module Data.Array.Knead.Simple.Private where
-
-import qualified Data.Array.Knead.Shape as Shape
-import qualified Data.Array.Knead.Expression as Expr
-
-import LLVM.DSL.Expression (Exp(Exp))
-
-import qualified LLVM.Extra.Multi.Value as MultiValue
-import qualified LLVM.Extra.Iterator as Iter
-import qualified LLVM.Extra.Maybe as Maybe
-import qualified LLVM.Core as LLVM
-
-import qualified Control.Category as Cat
-import qualified Control.Monad.HT as Monad
-import Control.Monad ((<=<), )
-
-import Prelude hiding (id, map, zipWith, replicate, )
-
-
-type Val = MultiValue.T
-type Code r a = LLVM.CodeGenFunction r (Val a)
-
-data Array sh a =
-   Array (Exp sh) (forall r. Val (Shape.Index sh) -> Code r a)
-
-shape :: Array sh a -> Exp sh
-shape (Array sh _) = sh
-
-(!) ::
-   (Shape.C sh,  Shape.Index sh  ~ ix) =>
-   Array sh a -> Exp ix -> Exp a
-(!) (Array _ code) (Exp ix) = Exp (code =<< ix)
-
-the :: (Shape.Scalar sh) => Array sh a -> Exp a
-the (Array z code) = Exp (code $ Shape.zeroIndex z)
-
-fromScalar :: (Shape.Scalar sh) => Exp a -> Array sh a
-fromScalar = fill Shape.scalar
-
-
-fill :: Exp sh -> Exp a -> Array sh a
-fill sh (Exp code) = Array sh (\_z -> code)
-
-
-{- |
-This class allows to implement functions without parameters
-for both simple and parameterized arrays.
--}
-class C array where
-   lift0 :: Array sh a -> array sh a
-   lift1 :: (Array sha a -> Array shb b) -> array sha a -> array shb b
-   lift2 ::
-      (Array sha a -> Array shb b -> Array shc c) ->
-      array sha a -> array shb b -> array shc c
-
-instance C Array where
-   lift0 = Cat.id
-   lift1 = Cat.id
-   lift2 = Cat.id
-
-
-gather ::
-   (C array,
-    Shape.C sh0, Shape.Index sh0 ~ ix0,
-    Shape.C sh1, Shape.Index sh1 ~ ix1,
-    MultiValue.C a) =>
-   array sh1 ix0 ->
-   array sh0 a ->
-   array sh1 a
-gather =
-   lift2 $ \(Array sh1 f) (Array _sh0 code) ->
-      Array sh1 (code <=< f)
-
-backpermute2 ::
-   (C array,
-    Shape.C sh0, Shape.Index sh0 ~ ix0,
-    Shape.C sh1, Shape.Index sh1 ~ ix1,
-    Shape.C sh,  Shape.Index sh  ~ ix) =>
-   Exp sh ->
-   (Exp ix -> Exp ix0) ->
-   (Exp ix -> Exp ix1) ->
-   (Exp a -> Exp b -> Exp c) ->
-   array sh0 a -> array sh1 b -> array sh c
-backpermute2 sh projectIndex0 projectIndex1 f =
-   lift2 $ \(Array _sha codeA) (Array _shb codeB) ->
-      Array sh
-         (\ix ->
-            Monad.liftJoin2 (Expr.unliftM2 f)
-               (codeA =<< Expr.unliftM1 projectIndex0 ix)
-               (codeB =<< Expr.unliftM1 projectIndex1 ix))
-
-
-id ::
-   (C array, Shape.C sh, Shape.Index sh ~ ix) =>
-   Exp sh -> array sh ix
-id sh = lift0 $ Array sh return
-
-map ::
-   (C array, Shape.C sh) =>
-   (Exp a -> Exp b) ->
-   array sh a -> array sh b
-map f =
-   lift1 $ \(Array sh code) ->
-      Array sh (Expr.unliftM1 f <=< code)
-
-mapWithIndex ::
-   (C array, Shape.C sh, Shape.Index sh ~ ix) =>
-   (Exp ix -> Exp a -> Exp b) ->
-   array sh a -> array sh b
-mapWithIndex f =
-   lift1 $ \(Array sh code) ->
-      Array sh (\ix -> Expr.unliftM2 f ix =<< code ix)
-
-
-fold1Code ::
-   (Shape.C sh, Shape.Index sh ~ ix, MultiValue.C a) =>
-   (Exp a -> Exp a -> Exp a) ->
-   Exp sh ->
-   (Val ix -> Code r a) ->
-   Code r a
-fold1Code f (Exp nc) code = do
-   n <- nc
-   fmap Maybe.fromJust $
-      Shape.loop
-         (\i0 macc0 -> do
-            a <- code i0
-            acc1 <- Maybe.run macc0 (return a) (flip (Expr.unliftM2 f) a)
-            return $ Maybe.just acc1)
-         n Maybe.nothing
-
-fold1 ::
-   (C array, Shape.C sh0, Shape.C sh1, MultiValue.C a) =>
-   (Exp a -> Exp a -> Exp a) ->
-   array (sh0, sh1) a -> array sh0 a
-fold1 f =
-   lift1 $ \(Array shs code) ->
-      case Expr.unzip shs of
-         (sh, s) -> Array sh $ fold1Code f s . MultiValue.curry code
-
-
-fold1All ::
-   (Shape.C sh, MultiValue.C a) =>
-   (Exp a -> Exp a -> Exp a) ->
-   Array sh a -> Exp a
-fold1All f (Array sh code) = Exp (fold1Code f sh code)
-
-
-findAllCode ::
-   (Shape.C sh, Shape.Index sh ~ ix, MultiValue.C a) =>
-   (Exp a -> Exp Bool) ->
-   Exp sh ->
-   (Val ix -> Code r a) ->
-   Code r (Maybe a)
-findAllCode p (Exp sh) code = do
-   n <- sh
-   finalFound <-
-      Iter.mapWhileState_
-         (\a _found -> do
-            MultiValue.Cons b <- Expr.unliftM1 p a
-            notb <- LLVM.inv b
-            return (notb, Maybe.fromBool b a))
-         (Iter.mapM code $ Shape.iterator n)
-         Maybe.nothing
-   Maybe.run finalFound
-      (return MultiValue.nothing)
-      (return . MultiValue.just)
-
-{- |
-In principle this can be implemented using fold1All
-but it has a short-cut semantics.
-@All@ means that it scans all dimensions
-but it does not mean that it finds all occurrences.
-If you want to get the index of the found element,
-please decorate the array elements with their indices before calling 'findAll'.
--}
-findAll ::
-   (Shape.C sh, MultiValue.C a) =>
-   (Exp a -> Exp Bool) ->
-   Array sh a -> Exp (Maybe a)
-findAll p (Array sh code) = Exp (findAllCode p sh code)
-
-
-class Process proc where
-
-
-infixl 3 $:.
-
-{- |
-Use this for combining several dimension manipulators.
-E.g.
-
-> apply (passAny $:. pick 3 $:. pass $:. replicate 10) array
-
-The constraint @(Process proc0, Process proc1)@ is a bit weak.
-We like to enforce that the type constructor like @Slice.T@
-is the same in @proc0@ and @proc1@, and only the parameters differ.
-Currently this coherence is achieved,
-because we only provide functions of type @proc0 -> proc1@ with this condition.
--}
-($:.) :: (Process proc0, Process proc1) => proc0 -> (proc0 -> proc1) -> proc1
-($:.) = flip ($)
diff --git a/src/Data/Array/Knead/Simple/ShapeDependent.hs b/src/Data/Array/Knead/Simple/ShapeDependent.hs
deleted file mode 100644
--- a/src/Data/Array/Knead/Simple/ShapeDependent.hs
+++ /dev/null
@@ -1,74 +0,0 @@
-{-# LANGUAGE TypeFamilies #-}
-module Data.Array.Knead.Simple.ShapeDependent where
-
-import qualified Data.Array.Knead.Simple.Private as Core
-import Data.Array.Knead.Simple.Private (Array(Array), )
-
-import qualified Data.Array.Knead.Shape as Shape
-import qualified Data.Array.Knead.Expression as Expr
-import Data.Array.Knead.Expression (Exp, )
-
-import qualified Control.Monad.HT as Monad
-import Control.Monad ((<=<), )
-
-
-shape :: (Core.C array, Shape.C sh, Shape.Scalar z) => array sh a -> array z sh
-shape = Core.lift1 $ Core.fromScalar . Core.shape
-
-backpermute ::
-   (Core.C array,
-    Shape.C sh0, Shape.Index sh0 ~ ix0,
-    Shape.C sh1, Shape.Index sh1 ~ ix1) =>
-   (Exp sh0 -> Exp sh1) ->
-   (Exp ix1 -> Exp ix0) ->
-   array sh0 a ->
-   array sh1 a
-backpermute createShape projectIndex =
-   Core.lift1 $ \(Array sh code) ->
-      Array (createShape sh)
-         (code <=< Expr.unliftM1 projectIndex)
-
-{- |
-This is between 'backpermute' and 'backpermute2'.
-You can access the shapes of two arrays,
-but only the content of one of them.
-This is necessary if the second array contributes only a virtual dimension.
--}
-backpermuteExtra ::
-   (Core.C array,
-    Shape.C sh0, Shape.Index sh0 ~ ix0,
-    Shape.C sh1, Shape.Index sh1 ~ ix1,
-    Shape.C sh,  Shape.Index sh  ~ ix) =>
-   (Exp sh0 -> Exp sh1 -> Exp sh) ->
-   (Exp ix -> Exp ix0) ->
-   array sh0 a -> array sh1 b -> array sh a
-backpermuteExtra newShape projectIndex =
-   Core.lift2 $ \(Array sh0 code) (Array sh1 _code) ->
-      Array (newShape sh0 sh1)
-         (\ix -> code =<< Expr.unliftM1 projectIndex ix)
-
-backpermute2 ::
-   (Core.C array,
-    Shape.C sh0, Shape.Index sh0 ~ ix0,
-    Shape.C sh1, Shape.Index sh1 ~ ix1,
-    Shape.C sh,  Shape.Index sh  ~ ix) =>
-   (Exp sh0 -> Exp sh1 -> Exp sh) ->
-   (Exp ix -> Exp ix0) ->
-   (Exp ix -> Exp ix1) ->
-   (Exp a -> Exp b -> Exp c) ->
-   array sh0 a -> array sh1 b -> array sh c
-backpermute2 combineShape projectIndex0 projectIndex1 f =
-   Core.lift2 $ \(Array sha codeA) (Array shb codeB) ->
-      Array (combineShape sha shb)
-         (\ix ->
-            Monad.liftJoin2 (Expr.unliftM2 f)
-               (codeA =<< Expr.unliftM1 projectIndex0 ix)
-               (codeB =<< Expr.unliftM1 projectIndex1 ix))
-
-fill ::
-   (Core.C array) =>
-   (Exp sh0 -> Exp sh1) -> Exp b ->
-   array sh0 a -> array sh1 b
-fill fsh a =
-   Core.lift1 $ \arr ->
-      Core.fill (fsh $ Core.shape arr) a
diff --git a/src/Data/Array/Knead/Simple/Slice.hs b/src/Data/Array/Knead/Simple/Slice.hs
deleted file mode 100644
--- a/src/Data/Array/Knead/Simple/Slice.hs
+++ /dev/null
@@ -1,198 +0,0 @@
-{- |
-Generate and apply index maps.
-This unifies the @replicate@ and @slice@ functions of the @accelerate@ package.
-However the structure of slicing and replicating cannot depend on parameters.
-If you need that, you must use 'ShapeDep.backpermute' and friends.
--}
-{-
-Some notes on the design choice:
-
-Instead of the shallow embedding implemented by the 'T' type,
-we could maintain a symbolic representation of the Slice and Replicate pattern,
-like the accelerate package does.
-We actually used that representation in former versions.
-It has however some drawbacks:
-
-* We need additional type functions that map from the pattern
-  to the source and the target shape and we need a proof,
-  that the images of these type functions are actually shapes.
-  This worked already, but was rather cumbersome.
-
-* We need a way to store and pass this pattern through the Parameter handler.
-  This yields new problems:
-  We need a wrapper type for wrapping Index, Shape, Slice, Replicate, Fold patterns.
-  Then the question is whether we use one Wrap type with a phantom parameter
-  or whether we define a Wrap type for every pattern type.
-  That is, the options are to write either
-
-  > Wrap Shape (Z:.Int:.Int)
-
-  or
-
-  > Shape (Z:.Int:.Int)
-
-  The first one seems to save us many duplicate instances of
-  Storable, MultiValue etc.
-  and it allows us easily to reuse the (:.) for all kinds of patterns.
-  However, we need a way to restrict the element type of the (:.)-list elements.
-  We can define that using variable ConstraintKinds,
-  but e.g. we are not able to add a Storable superclass constraint
-  to the instance Storable (Wrap constr).
-  That is, we are left with the second option
-  and had to define a lot of similar Storable, MultiValue instances.
--}
-{-# LANGUAGE GADTs #-}
-{-# LANGUAGE ExistentialQuantification #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE TypeOperators #-}
-module Data.Array.Knead.Simple.Slice (
-   T,
-   Cubic,
-   apply,
-   passAny,
-   pass,
-   pick,
-   pickFst,
-   pickSnd,
-   extrude,
-   extrudeFst,
-   extrudeSnd,
-   transpose,
-   (Core.$:.),
-
-   id,
-   first,
-   second,
-   compose,
-   ) where
-
-import qualified Data.Array.Knead.Simple.ShapeDependent as ShapeDep
-import qualified Data.Array.Knead.Simple.Private as Core
-
-import qualified Data.Array.Knead.Shape.Cubic.Int as Index
-import qualified Data.Array.Knead.Shape.Cubic as Cubic
-import qualified Data.Array.Knead.Shape as Shape
-import qualified Data.Array.Knead.Expression as Expr
-import Data.Array.Knead.Shape.Cubic ((#:.), (:.)((:.)), )
-import Data.Array.Knead.Expression (Exp, )
-
-import qualified LLVM.Extra.Multi.Value as MultiValue
-import LLVM.Extra.Multi.Value (atom, )
-
-import qualified Type.Data.Num.Unary as Unary
-
-import qualified Prelude as P
-import Prelude hiding (id, zipWith, zipWith3, zip, zip3, replicate, )
-
-
-
-{-
-This data type is almost identical to Core.Array.
-The only difference is,
-that the shape @sh1@ in T can depend on another shape @sh0@.
--}
-data T sh0 sh1 =
-   forall ix0 ix1.
-   (Shape.Index sh0 ~ ix0, Shape.Index sh1 ~ ix1) =>
-   Cons
-      (Exp sh0 -> Exp sh1)
-      (Exp ix1 -> Exp ix0)
-
-{- |
-This is essentially a 'ShapeDep.backpermute'.
--}
-apply ::
-   (Core.C array, Shape.C sh0, Shape.C sh1, MultiValue.C a) =>
-   T sh0 sh1 ->
-   array sh0 a ->
-   array sh1 a
-apply (Cons fsh fix) =
-   ShapeDep.backpermute fsh fix
-
-
-pickFst :: Exp (Shape.Index n) -> T (n,sh) sh
-pickFst i = Cons Expr.snd (Expr.zip i)
-
-pickSnd :: Exp (Shape.Index n) -> T (sh,n) sh
-pickSnd i = Cons Expr.fst (flip Expr.zip i)
-
-{- |
-Extrusion has the potential to do duplicate work.
-Only use it to add dimensions of size 1, e.g. numeric 1 or unit @()@
-or to duplicate slices of physical arrays.
--}
-extrudeFst :: Exp n -> T sh (n,sh)
-extrudeFst n = Cons (Expr.zip n) Expr.snd
-
-extrudeSnd :: Exp n -> T sh (sh,n)
-extrudeSnd n = Cons (flip Expr.zip n) Expr.fst
-
-transpose :: T (sh0,sh1) (sh1,sh0)
-transpose = Cons Expr.swap Expr.swap
-
-
--- Arrow combinators
-
-id :: T sh sh
-id = Cons P.id P.id
-
-first :: T sh0 sh1 -> T (sh0,sh) (sh1,sh)
-first (Cons fsh fix) = Cons (Expr.mapFst fsh) (Expr.mapFst fix)
-
-second :: T sh0 sh1 -> T (sh,sh0) (sh,sh1)
-second (Cons fsh fix) = Cons (Expr.mapSnd fsh) (Expr.mapSnd fix)
-
-infixr 1 `compose`
-
-compose :: T sh0 sh1 -> T sh1 sh2 -> T sh0 sh2
-compose (Cons fshA fixA) (Cons fshB fixB) = Cons (fshB . fshA) (fixA . fixB)
-
-
-type Cubic rank0 rank1 = T (Cubic.Shape rank0) (Cubic.Shape rank1)
-
-{- |
-Like @Any@ in @accelerate@.
--}
-passAny :: Cubic rank rank
-passAny = Cons P.id P.id
-
-{- |
-Like @All@ in @accelerate@.
--}
-pass ::
-   (Unary.Natural rank0, Unary.Natural rank1) =>
-   Cubic rank0 rank1 ->
-   Cubic (Unary.Succ rank0) (Unary.Succ rank1)
-pass (Cons fsh fix) =
-   Cons
-      (Expr.modify (atom:.atom) $ \(sh:.s) -> fsh sh :. s)
-      (Expr.modify (atom:.atom) $ \(ix:.i) -> fix ix :. i)
-
-{- |
-Like @Int@ in @accelerate/slice@.
--}
-pick ::
-   (Unary.Natural rank0, Unary.Natural rank1) =>
-   Exp Index.Int ->
-   Cubic rank0 rank1 ->
-   Cubic (Unary.Succ rank0) rank1
-pick i (Cons fsh fix) =
-   Cons
-      (fsh . Cubic.tail)
-      (\ix -> fix ix #:. i)
-
-{- |
-Like @Int@ in @accelerate/replicate@.
--}
-extrude ::
-   (Unary.Natural rank0, Unary.Natural rank1) =>
-   Exp Index.Int ->
-   Cubic rank0 rank1 ->
-   Cubic rank0 (Unary.Succ rank1)
-extrude n (Cons fsh fix) =
-   Cons
-      (\sh -> fsh sh #:. n)
-      (fix . Cubic.tail)
-
-
-instance Core.Process (T sh0 sh1) where
diff --git a/src/Data/Array/Knead/Simple/Symbolic.hs b/src/Data/Array/Knead/Simple/Symbolic.hs
deleted file mode 100644
--- a/src/Data/Array/Knead/Simple/Symbolic.hs
+++ /dev/null
@@ -1,93 +0,0 @@
-{-# LANGUAGE Rank2Types #-}
-{-# LANGUAGE GADTs #-}
-module Data.Array.Knead.Simple.Symbolic (
-   Core.Array,
-   Core.C(..),
-   Exp,
-   fix,
-   shape,
-   (Core.!),
-   Core.the,
-   Core.fromScalar,
-   Core.fill,
-   gather,
-   backpermute,
-   Core.backpermute2,
-   Core.id,
-   Core.map,
-   Core.mapWithIndex,
-   zipWith,
-   zipWith3,
-   zipWith4,
-   zip,
-   zip3,
-   zip4,
-   Core.fold1,
-   Core.fold1All,
-   Core.findAll,
-   ) where
-
-import qualified Data.Array.Knead.Simple.ShapeDependent as ShapeDep
-import qualified Data.Array.Knead.Simple.Private as Core
-import Data.Array.Knead.Simple.Private (Array, shape, gather, )
-
-import qualified Data.Array.Knead.Shape as Shape
-import qualified Data.Array.Knead.Expression as Expr
-import Data.Array.Knead.Expression (Exp, )
-
-import qualified LLVM.Extra.Multi.Value as MultiValue
-
-import Data.Function.HT (Id)
-
-import Prelude hiding (zipWith, zipWith3, zip, zip3, replicate, )
-
-
-fix :: Id (Array sh a)
-fix = id
-
-backpermute ::
-   (Shape.C sh0, Shape.Index sh0 ~ ix0,
-    Shape.C sh1, Shape.Index sh1 ~ ix1,
-    MultiValue.C a) =>
-   Exp sh1 ->
-   (Exp ix1 -> Exp ix0) ->
-   Array sh0 a ->
-   Array sh1 a
-backpermute sh1 f = gather (Core.map f (Core.id sh1))
-
-zipWith ::
-   (Core.C array, Shape.C sh) =>
-   (Exp a -> Exp b -> Exp c) ->
-   array sh a -> array sh b -> array sh c
-zipWith = ShapeDep.backpermute2 Shape.intersect id id
-
-zipWith3 ::
-   (Core.C array, Shape.C sh) =>
-   (Exp a -> Exp b -> Exp c -> Exp d) ->
-   array sh a -> array sh b -> array sh c -> array sh d
-zipWith3 f a b c =
-   zipWith (\ab -> uncurry f (Expr.unzip ab)) (zipWith Expr.zip a b) c
-
-zipWith4 ::
-   (Core.C array, Shape.C sh) =>
-   (Exp a -> Exp b -> Exp c -> Exp d -> Exp e) ->
-   array sh a -> array sh b -> array sh c -> array sh d -> array sh e
-zipWith4 f a b c d =
-   zipWith3 (\ab -> uncurry f (Expr.unzip ab)) (zipWith Expr.zip a b) c d
-
-
-zip ::
-   (Core.C array, Shape.C sh) =>
-   array sh a -> array sh b -> array sh (a,b)
-zip = zipWith (Expr.lift2 MultiValue.zip)
-
-zip3 ::
-   (Core.C array, Shape.C sh) =>
-   array sh a -> array sh b -> array sh c -> array sh (a,b,c)
-zip3 = zipWith3 (Expr.lift3 MultiValue.zip3)
-
-zip4 ::
-   (Core.C array, Shape.C sh) =>
-   array sh a -> array sh b -> array sh c -> array sh d ->
-   array sh (a,b,c,d)
-zip4 = zipWith4 (Expr.lift4 MultiValue.zip4)
diff --git a/src/Data/Array/Knead/Symbolic.hs b/src/Data/Array/Knead/Symbolic.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Array/Knead/Symbolic.hs
@@ -0,0 +1,94 @@
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE TypeOperators #-}
+module Data.Array.Knead.Symbolic (
+   Core.Array,
+   Core.C(..),
+   Exp,
+   fix,
+   shape,
+   (Core.!),
+   Core.the,
+   Core.fromScalar,
+   Core.fill,
+   gather,
+   backpermute,
+   Core.backpermute2,
+   Core.id,
+   Core.map,
+   Core.mapWithIndex,
+   zipWith,
+   zipWith3,
+   zipWith4,
+   zip,
+   zip3,
+   zip4,
+   Core.fold1,
+   Core.fold1All,
+   Core.findAll,
+   ) where
+
+import qualified Data.Array.Knead.Symbolic.ShapeDependent as ShapeDep
+import qualified Data.Array.Knead.Symbolic.Private as Core
+import Data.Array.Knead.Symbolic.Private (Array, shape, gather, )
+
+import qualified Data.Array.Knead.Shape as Shape
+import qualified Data.Array.Knead.Expression as Expr
+import Data.Array.Knead.Expression (Exp, )
+
+import qualified LLVM.Extra.Multi.Value as MultiValue
+
+import Data.Function.HT (Id)
+
+import Prelude hiding (zipWith, zipWith3, zip, zip3, replicate, )
+
+
+fix :: Id (Array sh a)
+fix = id
+
+backpermute ::
+   (Shape.C sh0, Shape.Index sh0 ~ ix0,
+    Shape.C sh1, Shape.Index sh1 ~ ix1,
+    MultiValue.C a) =>
+   Exp sh1 ->
+   (Exp ix1 -> Exp ix0) ->
+   Array sh0 a ->
+   Array sh1 a
+backpermute sh1 f = gather (Core.map f (Core.id sh1))
+
+zipWith ::
+   (Core.C array, Shape.C sh) =>
+   (Exp a -> Exp b -> Exp c) ->
+   array sh a -> array sh b -> array sh c
+zipWith = ShapeDep.backpermute2 Shape.intersect id id
+
+zipWith3 ::
+   (Core.C array, Shape.C sh) =>
+   (Exp a -> Exp b -> Exp c -> Exp d) ->
+   array sh a -> array sh b -> array sh c -> array sh d
+zipWith3 f a b c =
+   zipWith (\ab -> uncurry f (Expr.unzip ab)) (zipWith Expr.zip a b) c
+
+zipWith4 ::
+   (Core.C array, Shape.C sh) =>
+   (Exp a -> Exp b -> Exp c -> Exp d -> Exp e) ->
+   array sh a -> array sh b -> array sh c -> array sh d -> array sh e
+zipWith4 f a b c d =
+   zipWith3 (\ab -> uncurry f (Expr.unzip ab)) (zipWith Expr.zip a b) c d
+
+
+zip ::
+   (Core.C array, Shape.C sh) =>
+   array sh a -> array sh b -> array sh (a,b)
+zip = zipWith (Expr.lift2 MultiValue.zip)
+
+zip3 ::
+   (Core.C array, Shape.C sh) =>
+   array sh a -> array sh b -> array sh c -> array sh (a,b,c)
+zip3 = zipWith3 (Expr.lift3 MultiValue.zip3)
+
+zip4 ::
+   (Core.C array, Shape.C sh) =>
+   array sh a -> array sh b -> array sh c -> array sh d ->
+   array sh (a,b,c,d)
+zip4 = zipWith4 (Expr.lift4 MultiValue.zip4)
diff --git a/src/Data/Array/Knead/Symbolic/Fold.hs b/src/Data/Array/Knead/Symbolic/Fold.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Array/Knead/Symbolic/Fold.hs
@@ -0,0 +1,98 @@
+{- |
+Reduce selected dimensions.
+Alternatively you may reorder dimensions with 'ShapeDep.backpermute'
+and fold once along multiple dimensions.
+-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+module Data.Array.Knead.Symbolic.Fold (
+   T,
+   Cubic,
+   apply,
+   passAny,
+   pass,
+   fold,
+   (Core.$:.),
+   ) where
+
+import qualified Data.Array.Knead.Symbolic.Private as Core
+import Data.Array.Knead.Symbolic.Private (Array(Array), Code, Val, )
+
+import qualified Data.Array.Knead.Shape.Cubic.Int as Index
+import qualified Data.Array.Knead.Shape.Cubic as Cubic
+import qualified Data.Array.Knead.Shape as Shape
+import qualified Data.Array.Knead.Expression as Expr
+import Data.Array.Knead.Shape.Cubic ((#:.), (:.)((:.)), )
+
+import LLVM.DSL.Expression (Exp, unExp)
+
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import LLVM.Extra.Multi.Value (atom, )
+
+import qualified Type.Data.Num.Unary as Unary
+
+import Prelude hiding (zipWith, zipWith3, zip, zip3, replicate, )
+
+
+data T sh0 sh1 a =
+   forall ix0 ix1.
+   (Shape.Index sh0 ~ ix0, Shape.Index sh1 ~ ix1) =>
+   Cons
+      (Exp sh0 -> Exp sh1)
+      (forall r. Val sh0 -> (Val ix0 -> Code r a) -> (Val ix1 -> Code r a))
+
+
+apply ::
+   (Core.C array, Shape.C sh0, Shape.C sh1, MultiValue.C a) =>
+   T sh0 sh1 a ->
+   array sh0 a ->
+   array sh1 a
+apply (Cons fsh reduce) =
+   Core.lift1 $ \(Array sh code) ->
+      Array (fsh sh) (\ix -> do sh0 <- unExp sh; reduce sh0 code ix)
+
+
+type Cubic rank0 rank1 = T (Cubic.Shape rank0) (Cubic.Shape rank1)
+
+passAny :: Cubic rank rank a
+passAny = Cons id (const id)
+
+pass ::
+   (Unary.Natural rank0, Unary.Natural rank1, MultiValue.C a) =>
+   Cubic rank0 rank1 a ->
+   Cubic (Unary.Succ rank0) (Unary.Succ rank1) a
+pass (Cons fsh reduce) =
+   Cons
+      (Expr.modify (atom:.atom) $ \(sh:.s) -> fsh sh :. s)
+      (\sh code ->
+       Cubic.switchR $ \jx j ->
+          reduce (Cubic.tail sh) (\kx -> code (kx #:. j)) jx)
+
+
+fold1CodeLinear ::
+   (Unary.Natural rank, MultiValue.C a) =>
+   (Exp a -> Exp a -> Exp a) ->
+   Exp Index.Int ->
+   (Val (Cubic.Index (Unary.Succ rank)) -> Code r a) ->
+   (Val (Cubic.Index rank) -> Code r a)
+fold1CodeLinear f nc code ix =
+   Core.fold1Code f
+      (Expr.lift1 (MultiValue.compose . Shape.ZeroBased) $ Index.decons nc)
+      (\j -> code (ix #:. Index.cons j))
+
+fold ::
+   (Unary.Natural rank0, Unary.Natural rank1, MultiValue.C a) =>
+   (Exp a -> Exp a -> Exp a) ->
+   Cubic rank0 rank1 a ->
+   Cubic (Unary.Succ rank0) rank1 a
+fold f (Cons fsh reduce) =
+   Cons
+      (fsh . Cubic.tail)
+      (\sh code jx ->
+          reduce (Cubic.tail sh)
+             (fold1CodeLinear f (Expr.lift0 (Cubic.head sh)) code) jx)
+
+
+instance Core.Process (T sh0 sh1 a) where
diff --git a/src/Data/Array/Knead/Symbolic/Physical.hs b/src/Data/Array/Knead/Symbolic/Physical.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Array/Knead/Symbolic/Physical.hs
@@ -0,0 +1,195 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE ForeignFunctionInterface #-}
+module Data.Array.Knead.Symbolic.Physical (
+   Array,
+   shape,
+   toList,
+   fromList,
+   vectorFromList,
+   with,
+   render,
+   scanl1,
+   mapAccumLSimple,
+   scatter,
+   scatterMaybe,
+   permute,
+   ) where
+
+import qualified Data.Array.Knead.Symbolic.PhysicalPrivate as Priv
+import qualified Data.Array.Knead.Symbolic.Private as Sym
+import qualified Data.Array.Knead.Shape as Shape
+import qualified Data.Array.Knead.Expression as Expr
+import Data.Array.Knead.Symbolic.PhysicalPrivate (MarshalPtr)
+import Data.Array.Knead.Code (getElementPtr)
+
+import qualified LLVM.DSL.Execution as Code
+import LLVM.DSL.Expression (Exp, unExp)
+
+import qualified Data.Array.Comfort.Storable.Mutable.Unchecked as MutArray
+import qualified Data.Array.Comfort.Storable.Unchecked as Array
+import qualified Data.Array.Comfort.Shape as ComfortShape
+import Data.Array.Comfort.Storable.Unchecked (Array(Array))
+
+import qualified LLVM.Extra.Multi.Value.Storable as Storable
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Memory as Memory
+import qualified LLVM.Extra.Maybe as Maybe
+
+import qualified LLVM.Core as LLVM
+
+import Foreign.Storable (Storable, )
+import Foreign.ForeignPtr (withForeignPtr, mallocForeignPtrArray, )
+import Foreign.Ptr (FunPtr, Ptr, )
+
+import Control.Monad.HT (void, (<=<), )
+import Control.Applicative (liftA2, (<$>), )
+
+import Prelude2010 hiding (scanl1)
+import Prelude ()
+
+
+shape :: Array sh a -> sh
+shape = Array.shape
+
+toList ::
+   (Shape.C sh, Storable a) =>
+   Array sh a -> IO [a]
+toList = MutArray.toList <=< MutArray.unsafeThaw
+
+fromList ::
+   (Shape.C sh, Storable a) =>
+   sh -> [a] -> IO (Array sh a)
+fromList sh = MutArray.unsafeFreeze <=< MutArray.fromList sh
+
+vectorFromList ::
+   (Num n, Storable a) =>
+   [a] -> IO (Array (ComfortShape.ZeroBased n) a)
+vectorFromList xs =
+   Array.mapShape (\(Shape.ZeroBased n) -> Shape.ZeroBased $ fromIntegral n) <$>
+   (MutArray.unsafeFreeze =<< MutArray.vectorFromList xs)
+
+
+{- |
+The symbolic array is only valid inside the enclosed action.
+-}
+with ::
+   (Shape.C sh, Storable.C a) =>
+   (Sym.Array sh a -> IO b) ->
+   Array sh a -> IO b
+with f (Array sh fptr) =
+   withForeignPtr fptr $ \ptr ->
+      f $
+      Sym.Array
+         (Shape.value sh)
+         (\ix ->
+            Storable.load =<<
+               getElementPtr (Shape.value sh) (LLVM.valueOf ptr) ix)
+
+
+type Importer f = FunPtr f -> f
+
+foreign import ccall safe "dynamic" callShaper ::
+   Importer (LLVM.Ptr sh -> IO Shape.Size)
+
+foreign import ccall safe "dynamic" callRenderer ::
+   Importer (LLVM.Ptr sh -> Ptr a -> IO ())
+
+
+materialize ::
+   (Shape.C sh, Marshal.C sh, Storable.C a) =>
+   String ->
+   Exp sh ->
+   (LLVM.Value (MarshalPtr sh) ->
+    LLVM.Value (Ptr a) -> LLVM.CodeGenFunction () ()) ->
+   IO (Array sh a)
+materialize name esh code =
+   Marshal.alloca $ \lshptr -> do
+      (fsh, farr) <-
+         Code.compile name $
+         liftA2 (,)
+            (Code.createFunction callShaper "shape" $ \ptr -> do
+               sh <- unExp esh
+               Memory.store sh ptr
+               Shape.size sh)
+            (Code.createFunction callRenderer "fill" code)
+      n <- fsh lshptr
+      fptr <- mallocForeignPtrArray (fromIntegral n)
+      withForeignPtr fptr $ farr lshptr
+      sh <- Marshal.peek lshptr
+      return (Array sh fptr)
+
+render ::
+   (Shape.C sh, Marshal.C sh, Storable.C a) =>
+   Sym.Array sh a -> IO (Array sh a)
+render (Sym.Array esh code) =
+   materialize "render" esh $ \sptr ptr -> do
+      let step ix p = flip Storable.storeNext p =<< code ix
+      sh <- Shape.load esh sptr
+      void $ Shape.loop step sh ptr
+
+scanl1 ::
+   (Shape.C sh, Marshal.C sh,
+    Shape.C n, Marshal.C n,
+    Storable.C a, MultiValue.C a) =>
+   (Exp a -> Exp a -> Exp a) ->
+   Sym.Array (sh, n) a -> IO (Array (sh, n) a)
+scanl1 f (Sym.Array esh code) =
+   materialize "scanl1" esh $ \sptr ptr -> do
+      (sh, n) <- MultiValue.unzip <$> Shape.load esh sptr
+      let step ix ptrStart =
+             fmap fst $
+             (\body -> Shape.loop body n (ptrStart, Maybe.nothing)) $
+                   \k0 (ptr0, macc0) -> do
+                a <- code $ MultiValue.zip ix k0
+                acc1 <- Maybe.run macc0 (return a) (flip (Expr.unliftM2 f) a)
+                ptr1 <- Storable.storeNext acc1 ptr0
+                return (ptr1, Maybe.just acc1)
+      void $ Shape.loop step sh ptr
+
+mapAccumLSimple ::
+   (Shape.C sh, Marshal.C sh,
+    Shape.C n, Marshal.C n,
+    MultiValue.C acc, Storable.C x, Storable.C y) =>
+   (Exp acc -> Exp x -> Exp (acc,y)) ->
+   Sym.Array sh acc -> Sym.Array (sh, n) x -> IO (Array (sh, n) y)
+mapAccumLSimple f arrInit arrData =
+   materialize "mapAccumLSimple" (Sym.shape arrData) $
+      Priv.mapAccumLSimple f arrInit arrData
+
+scatterMaybe ::
+   (Shape.C sh0, Shape.Index sh0 ~ ix0,
+    Shape.C sh1, Shape.Index sh1 ~ ix1, Marshal.C sh1,
+    Storable.C a) =>
+   (Exp a -> Exp a -> Exp a) ->
+   Sym.Array sh1 a ->
+   Sym.Array sh0 (Maybe (ix1, a)) -> IO (Array sh1 a)
+scatterMaybe accum arrInit arrMap =
+   materialize "scatterMaybe" (Sym.shape arrInit) $
+      Priv.scatterMaybe accum arrInit arrMap
+
+scatter ::
+   (Shape.C sh0, Shape.Index sh0 ~ ix0,
+    Shape.C sh1, Shape.Index sh1 ~ ix1, Marshal.C sh1,
+    Storable.C a) =>
+   (Exp a -> Exp a -> Exp a) ->
+   Sym.Array sh1 a ->
+   Sym.Array sh0 (ix1, a) -> IO (Array sh1 a)
+scatter accum arrInit arrMap =
+   materialize "scatter" (Sym.shape arrInit) $
+      Priv.scatter accum arrInit arrMap
+
+permute ::
+   (Shape.C sh0, Shape.Index sh0 ~ ix0,
+    Shape.C sh1, Shape.Index sh1 ~ ix1, Marshal.C sh1,
+    Storable.C a) =>
+   (Exp a -> Exp a -> Exp a) ->
+   Sym.Array sh1 a ->
+   (Exp ix0 -> Exp ix1) ->
+   Sym.Array sh0 a ->
+   IO (Array sh1 a)
+permute accum deflt ixmap input =
+   scatter accum deflt
+      (Sym.mapWithIndex (Expr.lift2 MultiValue.zip . ixmap) input)
diff --git a/src/Data/Array/Knead/Symbolic/PhysicalPrivate.hs b/src/Data/Array/Knead/Symbolic/PhysicalPrivate.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Array/Knead/Symbolic/PhysicalPrivate.hs
@@ -0,0 +1,259 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+module Data.Array.Knead.Symbolic.PhysicalPrivate where
+
+import qualified Data.Array.Knead.Symbolic.Private as Sym
+import qualified Data.Array.Knead.Shape as Shape
+import qualified Data.Array.Knead.Expression as Expr
+import Data.Array.Knead.Code (getElementPtr)
+
+import LLVM.DSL.Expression (Exp, unExp)
+
+import qualified LLVM.Extra.Multi.Value.Storable as Storable
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Control as C
+
+import qualified LLVM.Core as LLVM
+
+import Foreign.Ptr (Ptr, )
+
+import qualified Control.Applicative.HT as App
+import Control.Monad.HT (void, )
+import Control.Applicative ((<$>), )
+
+import Data.Tuple.HT (mapSnd, )
+
+import Prelude2010
+import Prelude ()
+
+
+
+type MarshalPtr a = LLVM.Ptr (Marshal.Struct a)
+
+writeArray ::
+   (Shape.C sh, Shape.Index sh ~ ix, Storable.C a) =>
+   MultiValue.T sh ->
+   (MultiValue.T ix -> LLVM.CodeGenFunction r (MultiValue.T a)) ->
+   LLVM.Value (Ptr a) ->
+   LLVM.CodeGenFunction r (LLVM.Value (Ptr a))
+writeArray sh code ptr = do
+   let clear ix p = flip Storable.storeNext p =<< code ix
+   Shape.loop clear sh ptr
+
+
+mapAccumLLoop ::
+   (MultiValue.C acc, Storable.C b,
+    Shape.C sh, Shape.Index sh ~ ix) =>
+   (MultiValue.T ix -> LLVM.CodeGenFunction r (MultiValue.T a)) ->
+   (Exp acc -> Exp a -> Exp (acc, b)) ->
+   MultiValue.T sh ->
+   LLVM.Value (Ptr b) -> MultiValue.T acc ->
+   LLVM.CodeGenFunction r (LLVM.Value (Ptr b), MultiValue.T acc)
+mapAccumLLoop code f n yPtr accInit = do
+   let step k0 (ptr0, acc0) = do
+         x <- code k0
+         (acc1,y) <- MultiValue.unzip <$> Expr.unliftM2 f acc0 x
+         ptr1 <- Storable.storeNext y ptr0
+         return (ptr1, acc1)
+   Shape.loop step n (yPtr, accInit)
+
+mapAccumLSimple ::
+   (Shape.C sh, Marshal.C sh,
+    Shape.C n, Marshal.C n,
+    MultiValue.C acc,
+    Storable.C x,
+    Storable.C y) =>
+   (Exp acc -> Exp x -> Exp (acc,y)) ->
+   Sym.Array sh acc -> Sym.Array (sh, n) x ->
+   LLVM.Value (MarshalPtr (sh,n)) ->
+   LLVM.Value (Ptr y) ->
+   LLVM.CodeGenFunction r ()
+mapAccumLSimple f (Sym.Array _ initCode) (Sym.Array esh code) sptr ptr = do
+   (sh, n) <- MultiValue.unzip <$> Shape.load esh sptr
+   let step ix ptrStart = do
+         accInit <- initCode ix
+         fst <$> mapAccumLLoop (code . MultiValue.zip ix) f n ptrStart accInit
+   void $ Shape.loop step sh ptr
+
+mapAccumLSequence ::
+   (Shape.C n, Marshal.C n,
+    MultiValue.C acc, Storable.C final,
+    Storable.C x,
+    Storable.C y) =>
+   (Exp acc -> Exp x -> Exp (acc,y)) ->
+   (Exp acc -> Exp final) ->
+   Exp acc -> Sym.Array n x ->
+   LLVM.Value (Ptr final) ->
+   LLVM.Value (MarshalPtr n) ->
+   LLVM.Value (Ptr y) ->
+   LLVM.CodeGenFunction r ()
+mapAccumLSequence f final initExp (Sym.Array esh code) accPtr sptr yPtr = do
+   n <- Shape.load esh sptr
+   accInit <- unExp initExp
+   accExit <- snd <$> mapAccumLLoop code f n yPtr accInit
+   flip Storable.store accPtr =<< Expr.unliftM1 final accExit
+
+mapAccumL ::
+   (Shape.C sh, Marshal.C sh,
+    Shape.C n, Marshal.C n,
+    MultiValue.C acc, Storable.C final,
+    Storable.C x,
+    Storable.C y) =>
+   (Exp acc -> Exp x -> Exp (acc,y)) ->
+   (Exp acc -> Exp final) ->
+   Sym.Array sh acc -> Sym.Array (sh, n) x ->
+   (LLVM.Value (MarshalPtr sh), LLVM.Value (Ptr final)) ->
+   (LLVM.Value (MarshalPtr (sh,n)), LLVM.Value (Ptr y)) ->
+   LLVM.CodeGenFunction r ()
+mapAccumL f final (Sym.Array _ initCode) (Sym.Array esh code)
+      (_, accPtr) (sptr, yPtr) = do
+   (sh, n) <- MultiValue.unzip <$> Shape.load esh sptr
+   let step ix (accPtr0, yPtrStart) = do
+         accInit <- initCode ix
+         (ptrStop, accExit) <-
+            mapAccumLLoop (code . MultiValue.zip ix) f n yPtrStart accInit
+         accPtr1 <-
+            flip Storable.storeNext accPtr0
+               =<< Expr.unliftM1 final accExit
+         return (accPtr1, ptrStop)
+   void $ Shape.loop step sh (accPtr,yPtr)
+
+foldOuterL ::
+   (Shape.C sh, Marshal.C sh,
+    Shape.C n, Marshal.C n,
+    Storable.C a) =>
+   (Exp a -> Exp b -> Exp a) ->
+   Sym.Array sh a -> Sym.Array (n,sh) b ->
+   LLVM.Value (MarshalPtr sh) ->
+   LLVM.Value (Ptr a) ->
+   LLVM.CodeGenFunction r ()
+foldOuterL f (Sym.Array _ initCode) (Sym.Array esh code) sptr ptr = do
+   sh <- Shape.load (Expr.snd esh) sptr
+   n <- MultiValue.fst <$> unExp esh
+   void $ writeArray sh initCode ptr
+
+   let step k ix ptr0 = do
+         b <- code $ MultiValue.zip k ix
+         a0 <- Storable.load ptr0
+         a1 <- Expr.unliftM2 f a0 b
+         Storable.storeNext a1 ptr0
+   void $ Shape.loop (\k () -> void $ Shape.loop (step k) sh ptr) n ()
+
+{- |
+We need a scalar Shape type @n@.
+Scalar Shape types could be distinguished from other Shape types
+by the fact that you can convert any Index into a Shape.
+-}
+mapFilter ::
+   (Shape.Sequence n, Marshal.C n,
+    Storable.C b) =>
+   (Exp a -> Exp b) ->
+   (Exp a -> Exp Bool) ->
+   Sym.Array n a ->
+   LLVM.Value (MarshalPtr n) ->
+   LLVM.Value (Ptr b) ->
+   LLVM.CodeGenFunction r (MultiValue.T n)
+mapFilter f p (Sym.Array esh code) sptr ptr = do
+   n <- Shape.load esh sptr
+   let step ix (dstPtr,dstIx) = do
+         a <- code ix
+         MultiValue.Cons c <- Expr.unliftM1 p a
+         C.ifThen c (dstPtr,dstIx)
+            (App.lift2 (,)
+               (flip Storable.storeNext dstPtr =<< Expr.unliftM1 f a)
+               (MultiValue.inc dstIx))
+   Shape.sequenceShapeFromIndex . snd
+      =<< Shape.loop step n (ptr, MultiValue.zero)
+
+filterOuter ::
+   (Shape.Sequence n, Marshal.C n,
+    Shape.C sh, Marshal.C sh,
+    Storable.C a) =>
+   Sym.Array n Bool ->
+   Sym.Array (n,sh) a ->
+   LLVM.Value (MarshalPtr (n,sh)) ->
+   LLVM.Value (Ptr a) ->
+   LLVM.CodeGenFunction r (MultiValue.T (n,sh))
+filterOuter (Sym.Array _eish selectCode) (Sym.Array esh code) sptr ptr = do
+   (n,sh) <- MultiValue.unzip <$> Shape.load esh sptr
+   let step k (dstPtr0,dstK) = do
+         MultiValue.Cons c <- selectCode k
+         C.ifThen c (dstPtr0,dstK)
+            (do
+               dstPtr1 <- writeArray sh (code . MultiValue.zip k) dstPtr0
+               (,) dstPtr1 <$> MultiValue.inc dstK)
+   finalN <-
+      Shape.sequenceShapeFromIndex . snd
+         =<< Shape.loop step n (ptr, MultiValue.zero)
+   return $ MultiValue.zip finalN sh
+
+
+scatterMaybe ::
+   (Shape.C sh0, Shape.Index sh0 ~ ix0,
+    Shape.C sh1, Shape.Index sh1 ~ ix1,
+    Marshal.C sh1,
+    Storable.C a) =>
+   (Exp a -> Exp a -> Exp a) ->
+   Sym.Array sh1 a -> Sym.Array sh0 (Maybe (ix1, a)) ->
+   LLVM.Value (MarshalPtr sh1) ->
+   LLVM.Value (Ptr a) ->
+   LLVM.CodeGenFunction r ()
+scatterMaybe accum (Sym.Array esh codeInit) (Sym.Array eish codeMap)
+      sptr ptr = do
+
+   sh <- Shape.load esh sptr
+   void $ writeArray sh codeInit ptr
+
+   ish <- unExp eish
+   let fill ix () = do
+         (MultiValue.Cons c, (jx, a)) <-
+            mapSnd MultiValue.unzip . MultiValue.splitMaybe <$> codeMap ix
+         C.ifThen c () $ do
+            p <- getElementPtr sh ptr jx
+            flip Storable.store p
+               =<< Expr.unliftM2 (flip accum) a
+               =<< Storable.load p
+   Shape.loop fill ish ()
+
+scatter ::
+   (Shape.C sh0, Shape.Index sh0 ~ ix0,
+    Shape.C sh1, Shape.Index sh1 ~ ix1,
+    Marshal.C sh1,
+    Storable.C a) =>
+   (Exp a -> Exp a -> Exp a) ->
+   Sym.Array sh1 a ->
+   Sym.Array sh0 (Shape.Index sh1, a) ->
+   LLVM.Value (MarshalPtr sh1) ->
+   LLVM.Value (Ptr a) ->
+   LLVM.CodeGenFunction r ()
+scatter accum (Sym.Array esh codeInit) (Sym.Array eish codeMap) sptr ptr = do
+   sh <- Shape.load esh sptr
+   void $ writeArray sh codeInit ptr
+
+   ish <- unExp eish
+   let fill ix () = do
+         (jx, a) <- MultiValue.unzip <$> codeMap ix
+         p <- getElementPtr sh ptr jx
+         flip Storable.store p
+            =<< Expr.unliftM2 (flip accum) a
+            =<< Storable.load p
+   Shape.loop fill ish ()
+
+addDimension ::
+   (Shape.C n, Marshal.C n, Shape.Index n ~ k,
+    Shape.C sh, Marshal.C sh,
+    Storable.C b) =>
+   Exp n ->
+   (Exp k -> Exp a -> Exp b) ->
+   Sym.Array sh a ->
+   LLVM.Value (MarshalPtr (sh,n)) ->
+   LLVM.Value (Ptr b) ->
+   LLVM.CodeGenFunction r ()
+addDimension en select (Sym.Array esh code) sptr ptr = do
+   (sh,n) <- MultiValue.unzip <$> Shape.load (Expr.zip esh en) sptr
+
+   let fill ix ptr0 = do
+         a <- code ix
+         writeArray n (\k -> Expr.unliftM2 select k a) ptr0
+   void $ Shape.loop fill sh ptr
diff --git a/src/Data/Array/Knead/Symbolic/Private.hs b/src/Data/Array/Knead/Symbolic/Private.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Array/Knead/Symbolic/Private.hs
@@ -0,0 +1,204 @@
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+module Data.Array.Knead.Symbolic.Private where
+
+import qualified Data.Array.Knead.Shape as Shape
+import qualified Data.Array.Knead.Expression as Expr
+
+import LLVM.DSL.Expression (Exp(Exp))
+
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Iterator as Iter
+import qualified LLVM.Extra.Maybe as Maybe
+import qualified LLVM.Core as LLVM
+
+import qualified Control.Category as Cat
+import qualified Control.Monad.HT as Monad
+import Control.Monad ((<=<), )
+
+import Prelude hiding (id, map, zipWith, replicate, )
+
+
+type Val = MultiValue.T
+type Code r a = LLVM.CodeGenFunction r (Val a)
+
+data Array sh a =
+   Array (Exp sh) (forall r. Val (Shape.Index sh) -> Code r a)
+
+shape :: Array sh a -> Exp sh
+shape (Array sh _) = sh
+
+(!) ::
+   (Shape.C sh,  Shape.Index sh  ~ ix) =>
+   Array sh a -> Exp ix -> Exp a
+(!) (Array _ code) (Exp ix) = Exp (code =<< ix)
+
+the :: (Shape.Scalar sh) => Array sh a -> Exp a
+the (Array z code) = Exp (code $ Shape.zeroIndex z)
+
+fromScalar :: (Shape.Scalar sh) => Exp a -> Array sh a
+fromScalar = fill Shape.scalar
+
+
+fill :: Exp sh -> Exp a -> Array sh a
+fill sh (Exp code) = Array sh (\_z -> code)
+
+
+{- |
+This class allows to implement functions without parameters
+for both simple and parameterized arrays.
+-}
+class C array where
+   lift0 :: Array sh a -> array sh a
+   lift1 :: (Array sha a -> Array shb b) -> array sha a -> array shb b
+   lift2 ::
+      (Array sha a -> Array shb b -> Array shc c) ->
+      array sha a -> array shb b -> array shc c
+
+instance C Array where
+   lift0 = Cat.id
+   lift1 = Cat.id
+   lift2 = Cat.id
+
+
+gather ::
+   (C array,
+    Shape.C sh0, Shape.Index sh0 ~ ix0,
+    Shape.C sh1, Shape.Index sh1 ~ ix1,
+    MultiValue.C a) =>
+   array sh1 ix0 ->
+   array sh0 a ->
+   array sh1 a
+gather =
+   lift2 $ \(Array sh1 f) (Array _sh0 code) ->
+      Array sh1 (code <=< f)
+
+backpermute2 ::
+   (C array,
+    Shape.C sh0, Shape.Index sh0 ~ ix0,
+    Shape.C sh1, Shape.Index sh1 ~ ix1,
+    Shape.C sh,  Shape.Index sh  ~ ix) =>
+   Exp sh ->
+   (Exp ix -> Exp ix0) ->
+   (Exp ix -> Exp ix1) ->
+   (Exp a -> Exp b -> Exp c) ->
+   array sh0 a -> array sh1 b -> array sh c
+backpermute2 sh projectIndex0 projectIndex1 f =
+   lift2 $ \(Array _sha codeA) (Array _shb codeB) ->
+      Array sh
+         (\ix ->
+            Monad.liftJoin2 (Expr.unliftM2 f)
+               (codeA =<< Expr.unliftM1 projectIndex0 ix)
+               (codeB =<< Expr.unliftM1 projectIndex1 ix))
+
+
+id ::
+   (C array, Shape.C sh, Shape.Index sh ~ ix) =>
+   Exp sh -> array sh ix
+id sh = lift0 $ Array sh return
+
+map ::
+   (C array, Shape.C sh) =>
+   (Exp a -> Exp b) ->
+   array sh a -> array sh b
+map f =
+   lift1 $ \(Array sh code) ->
+      Array sh (Expr.unliftM1 f <=< code)
+
+mapWithIndex ::
+   (C array, Shape.C sh, Shape.Index sh ~ ix) =>
+   (Exp ix -> Exp a -> Exp b) ->
+   array sh a -> array sh b
+mapWithIndex f =
+   lift1 $ \(Array sh code) ->
+      Array sh (\ix -> Expr.unliftM2 f ix =<< code ix)
+
+
+fold1Code ::
+   (Shape.C sh, Shape.Index sh ~ ix, MultiValue.C a) =>
+   (Exp a -> Exp a -> Exp a) ->
+   Exp sh ->
+   (Val ix -> Code r a) ->
+   Code r a
+fold1Code f (Exp nc) code = do
+   n <- nc
+   fmap Maybe.fromJust $
+      Shape.loop
+         (\i0 macc0 -> do
+            a <- code i0
+            acc1 <- Maybe.run macc0 (return a) (flip (Expr.unliftM2 f) a)
+            return $ Maybe.just acc1)
+         n Maybe.nothing
+
+fold1 ::
+   (C array, Shape.C sh0, Shape.C sh1, MultiValue.C a) =>
+   (Exp a -> Exp a -> Exp a) ->
+   array (sh0, sh1) a -> array sh0 a
+fold1 f =
+   lift1 $ \(Array shs code) ->
+      case Expr.unzip shs of
+         (sh, s) -> Array sh $ fold1Code f s . MultiValue.curry code
+
+
+fold1All ::
+   (Shape.C sh, MultiValue.C a) =>
+   (Exp a -> Exp a -> Exp a) ->
+   Array sh a -> Exp a
+fold1All f (Array sh code) = Exp (fold1Code f sh code)
+
+
+findAllCode ::
+   (Shape.C sh, Shape.Index sh ~ ix, MultiValue.C a) =>
+   (Exp a -> Exp Bool) ->
+   Exp sh ->
+   (Val ix -> Code r a) ->
+   Code r (Maybe a)
+findAllCode p (Exp sh) code = do
+   n <- sh
+   finalFound <-
+      Iter.mapWhileState_
+         (\a _found -> do
+            MultiValue.Cons b <- Expr.unliftM1 p a
+            notb <- LLVM.inv b
+            return (notb, Maybe.fromBool b a))
+         (Iter.mapM code $ Shape.iterator n)
+         Maybe.nothing
+   Maybe.run finalFound
+      (return MultiValue.nothing)
+      (return . MultiValue.just)
+
+{- |
+In principle this can be implemented using fold1All
+but it has a short-cut semantics.
+@All@ means that it scans all dimensions
+but it does not mean that it finds all occurrences.
+If you want to get the index of the found element,
+please decorate the array elements with their indices before calling 'findAll'.
+-}
+findAll ::
+   (Shape.C sh, MultiValue.C a) =>
+   (Exp a -> Exp Bool) ->
+   Array sh a -> Exp (Maybe a)
+findAll p (Array sh code) = Exp (findAllCode p sh code)
+
+
+class Process proc where
+
+
+infixl 3 $:.
+
+{- |
+Use this for combining several dimension manipulators.
+E.g.
+
+> apply (passAny $:. pick 3 $:. pass $:. replicate 10) array
+
+The constraint @(Process proc0, Process proc1)@ is a bit weak.
+We like to enforce that the type constructor like @Slice.T@
+is the same in @proc0@ and @proc1@, and only the parameters differ.
+Currently this coherence is achieved,
+because we only provide functions of type @proc0 -> proc1@ with this condition.
+-}
+($:.) :: (Process proc0, Process proc1) => proc0 -> (proc0 -> proc1) -> proc1
+($:.) = flip ($)
diff --git a/src/Data/Array/Knead/Symbolic/Render.hs b/src/Data/Array/Knead/Symbolic/Render.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Array/Knead/Symbolic/Render.hs
@@ -0,0 +1,200 @@
+{-# LANGUAGE TypeFamilies #-}
+{- |
+Simplify running the @render@ function by handling passing of parameters.
+-}
+module Data.Array.Knead.Symbolic.Render (
+   run,
+   MarshalExp(..),
+   MapFilter(..),
+   FilterOuter(..),
+   Scatter(..),
+   ScatterMaybe(..),
+   MapAccumLSimple(..),
+   MapAccumLSequence(..),
+   MapAccumL(..),
+   FoldOuterL(..),
+   AddDimension(..),
+   ) where
+
+import qualified Data.Array.Knead.Parameterized.PhysicalHull as PhysHullP
+import qualified Data.Array.Knead.Parameterized.Physical as PhysP
+import qualified Data.Array.Knead.Parameterized.Private as Sym
+import qualified Data.Array.Knead.Symbolic.Physical as Phys
+import qualified Data.Array.Knead.Symbolic.Private as Core
+import qualified Data.Array.Knead.Shape as Shape
+import Data.Array.Knead.Parameterized.PhysicalHull
+         (MapFilter, FilterOuter,
+          MapAccumLSimple, MapAccumLSequence, MapAccumL, FoldOuterL,
+          Scatter, ScatterMaybe, AddDimension)
+import Data.Array.Knead.Expression (Exp, )
+
+import qualified LLVM.DSL.Parameter as Param
+
+import qualified LLVM.Extra.Multi.Value.Storable as Storable
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
+
+import Control.Arrow (arr, )
+import Control.Applicative (liftA2, liftA3, pure, (<*>), )
+
+import Data.Tuple.HT (fst3, snd3, thd3, )
+
+import Prelude2010
+import Prelude ()
+
+
+
+class C f where
+   type Plain f
+   build :: Sym.Hull p f -> IO (p -> Plain f)
+
+instance
+   (Marshal.C sh, Shape.C sh, Storable.C a) =>
+      C (Core.Array sh a) where
+   type Plain (Core.Array sh a) = IO (Phys.Array sh a)
+   build = PhysHullP.render
+
+instance
+   (Shape.Sequence n, Marshal.C n,
+    Storable.C b, MultiValue.C b) =>
+      C (MapFilter n a b) where
+   type Plain (MapFilter n a b) = IO (Phys.Array n b)
+   build = PhysHullP.mapFilter
+
+instance
+   (Shape.Sequence n, Marshal.C n,
+    Shape.C sh, Marshal.C sh,
+    Storable.C a, MultiValue.C a) =>
+      C (FilterOuter n sh a) where
+   type Plain (FilterOuter n sh a) = IO (Phys.Array (n,sh) a)
+   build = PhysHullP.filterOuter
+
+instance
+   (Shape.C sh0, Marshal.C sh0,
+    Shape.C sh1, Marshal.C sh1,
+    Storable.C a, MultiValue.C a) =>
+      C (Scatter sh0 sh1 a) where
+   type Plain (Scatter sh0 sh1 a) = IO (Phys.Array sh1 a)
+   build = PhysHullP.scatter
+
+instance
+   (Shape.C sh0, Marshal.C sh0,
+    Shape.C sh1, Marshal.C sh1,
+    Storable.C a, MultiValue.C a) =>
+      C (ScatterMaybe sh0 sh1 a) where
+   type Plain (ScatterMaybe sh0 sh1 a) = IO (Phys.Array sh1 a)
+   build = PhysHullP.scatterMaybe
+
+instance
+   (Shape.C sh, Marshal.C sh,
+    Shape.C n, Marshal.C n,
+    MultiValue.C acc,
+    Storable.C a, MultiValue.C a,
+    Storable.C b, MultiValue.C b) =>
+      C (MapAccumLSimple sh n acc a b) where
+   type Plain (MapAccumLSimple sh n acc a b) = IO (Phys.Array (sh,n) b)
+   build = PhysHullP.mapAccumLSimple
+
+instance
+   (Shape.C n, Marshal.C n,
+    MultiValue.C acc,
+    Storable.C final, MultiValue.C final,
+    Storable.C a, MultiValue.C a,
+    Storable.C b, MultiValue.C b) =>
+      C (MapAccumLSequence n acc final a b) where
+   type Plain (MapAccumLSequence n acc final a b) = IO (final, Phys.Array n b)
+   build = PhysHullP.mapAccumLSequence
+
+instance
+   (Shape.C sh, Marshal.C sh,
+    Shape.C n, Marshal.C n,
+    MultiValue.C acc,
+    Storable.C final, MultiValue.C final,
+    Storable.C a, MultiValue.C a,
+    Storable.C b, MultiValue.C b) =>
+      C (MapAccumL sh n acc final a b) where
+   type Plain (MapAccumL sh n acc final a b) =
+            IO (Phys.Array sh final, Phys.Array (sh,n) b)
+   build = PhysHullP.mapAccumL
+
+instance
+   (Shape.C n, Marshal.C n,
+    Shape.C sh, Marshal.C sh,
+    Storable.C a, MultiValue.C a,
+    Storable.C b, MultiValue.C b) =>
+      C (FoldOuterL n sh a b) where
+   type Plain (FoldOuterL n sh a b) = IO (Phys.Array sh a)
+   build = PhysHullP.foldOuterL
+
+instance
+   (Shape.C sh, Marshal.C sh,
+    Shape.C n, Marshal.C n,
+    Storable.C b, MultiValue.C b) =>
+      C (AddDimension sh n a b) where
+   type Plain (AddDimension sh n a b) = IO (Phys.Array (sh,n) b)
+   build = PhysHullP.addDimension
+
+
+singleton :: Exp a -> Core.Array () a
+singleton = Core.fromScalar
+
+instance (Storable.C a, MultiValue.C a) => C (Exp a) where
+   type Plain (Exp a) = IO a
+   build = PhysP.the . Sym.runHull . fmap singleton
+
+newtype MarshalExp a = MarshalExp {getMarshalExp :: Exp a}
+
+instance (Marshal.C a) => C (MarshalExp a) where
+   type Plain (MarshalExp a) = IO a
+   build = PhysP.theMarshal . Sym.runHull . fmap (singleton . getMarshalExp)
+
+instance (Argument arg, C func) => C (arg -> func) where
+   type Plain (arg -> func) = PlainArg arg -> Plain func
+   build f = fmap curry $ build $ Sym.extendHull fst f <*> buildArg (arr snd)
+
+
+class Argument arg where
+   type PlainArg arg
+   buildArg :: Param.T p (PlainArg arg) -> Sym.Hull p arg
+
+instance
+   (Shape.C sh, Marshal.C sh, Storable.C a) =>
+      Argument (Core.Array sh a) where
+   type PlainArg (Core.Array sh a) = Phys.Array sh a
+   buildArg = Sym.arrayHull . PhysP.feed
+
+instance (Marshal.C a) => Argument (Exp a) where
+   type PlainArg (Exp a) = a
+   buildArg = Sym.expHull . Sym.expParam
+
+instance (Argument a, Argument b) => Argument (a,b) where
+   type PlainArg (a,b) = (PlainArg a, PlainArg b)
+   buildArg p = liftA2 (,) (buildArg $ fmap fst p) (buildArg $ fmap snd p)
+
+instance (Argument a, Argument b, Argument c) => Argument (a,b,c) where
+   type PlainArg (a,b,c) = (PlainArg a, PlainArg b, PlainArg c)
+   buildArg p =
+      liftA3 (,,)
+         (buildArg $ fmap fst3 p) (buildArg $ fmap snd3 p) (buildArg $ fmap thd3 p)
+
+
+run :: (C f) => f -> IO (Plain f)
+run f = fmap ($ ()) $ build $ pure f
+
+
+
+_example ::
+   (Marshal.C x,
+    Shape.C sha, Marshal.C sha, Storable.C a,
+    Shape.C shb, Marshal.C shb, Storable.C b,
+    Shape.C shc, Marshal.C shc, Storable.C c) =>
+   (Exp x -> Core.Array sha a -> Core.Array shb b -> Core.Array shc c) ->
+   IO (x -> Phys.Array sha a -> Phys.Array shb b -> IO (Phys.Array shc c))
+_example f =
+   fmap (\g -> curry $ curry g) $
+   PhysP.render $
+   Sym.runHull $
+   pure f
+      <*> Sym.expHull (Sym.expParam $ arr (fst.fst))
+      <*> Sym.arrayHull (PhysP.feed $ arr (snd.fst))
+      <*> Sym.arrayHull (PhysP.feed $ arr snd)
diff --git a/src/Data/Array/Knead/Symbolic/ShapeDependent.hs b/src/Data/Array/Knead/Symbolic/ShapeDependent.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Array/Knead/Symbolic/ShapeDependent.hs
@@ -0,0 +1,75 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+module Data.Array.Knead.Symbolic.ShapeDependent where
+
+import qualified Data.Array.Knead.Symbolic.Private as Core
+import Data.Array.Knead.Symbolic.Private (Array(Array), )
+
+import qualified Data.Array.Knead.Shape as Shape
+import qualified Data.Array.Knead.Expression as Expr
+import Data.Array.Knead.Expression (Exp, )
+
+import qualified Control.Monad.HT as Monad
+import Control.Monad ((<=<), )
+
+
+shape :: (Core.C array, Shape.C sh, Shape.Scalar z) => array sh a -> array z sh
+shape = Core.lift1 $ Core.fromScalar . Core.shape
+
+backpermute ::
+   (Core.C array,
+    Shape.C sh0, Shape.Index sh0 ~ ix0,
+    Shape.C sh1, Shape.Index sh1 ~ ix1) =>
+   (Exp sh0 -> Exp sh1) ->
+   (Exp ix1 -> Exp ix0) ->
+   array sh0 a ->
+   array sh1 a
+backpermute createShape projectIndex =
+   Core.lift1 $ \(Array sh code) ->
+      Array (createShape sh)
+         (code <=< Expr.unliftM1 projectIndex)
+
+{- |
+This is between 'backpermute' and 'backpermute2'.
+You can access the shapes of two arrays,
+but only the content of one of them.
+This is necessary if the second array contributes only a virtual dimension.
+-}
+backpermuteExtra ::
+   (Core.C array,
+    Shape.C sh0, Shape.Index sh0 ~ ix0,
+    Shape.C sh1, Shape.Index sh1 ~ ix1,
+    Shape.C sh,  Shape.Index sh  ~ ix) =>
+   (Exp sh0 -> Exp sh1 -> Exp sh) ->
+   (Exp ix -> Exp ix0) ->
+   array sh0 a -> array sh1 b -> array sh a
+backpermuteExtra newShape projectIndex =
+   Core.lift2 $ \(Array sh0 code) (Array sh1 _code) ->
+      Array (newShape sh0 sh1)
+         (\ix -> code =<< Expr.unliftM1 projectIndex ix)
+
+backpermute2 ::
+   (Core.C array,
+    Shape.C sh0, Shape.Index sh0 ~ ix0,
+    Shape.C sh1, Shape.Index sh1 ~ ix1,
+    Shape.C sh,  Shape.Index sh  ~ ix) =>
+   (Exp sh0 -> Exp sh1 -> Exp sh) ->
+   (Exp ix -> Exp ix0) ->
+   (Exp ix -> Exp ix1) ->
+   (Exp a -> Exp b -> Exp c) ->
+   array sh0 a -> array sh1 b -> array sh c
+backpermute2 combineShape projectIndex0 projectIndex1 f =
+   Core.lift2 $ \(Array sha codeA) (Array shb codeB) ->
+      Array (combineShape sha shb)
+         (\ix ->
+            Monad.liftJoin2 (Expr.unliftM2 f)
+               (codeA =<< Expr.unliftM1 projectIndex0 ix)
+               (codeB =<< Expr.unliftM1 projectIndex1 ix))
+
+fill ::
+   (Core.C array) =>
+   (Exp sh0 -> Exp sh1) -> Exp b ->
+   array sh0 a -> array sh1 b
+fill fsh a =
+   Core.lift1 $ \arr ->
+      Core.fill (fsh $ Core.shape arr) a
diff --git a/src/Data/Array/Knead/Symbolic/Slice.hs b/src/Data/Array/Knead/Symbolic/Slice.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Array/Knead/Symbolic/Slice.hs
@@ -0,0 +1,198 @@
+{- |
+Generate and apply index maps.
+This unifies the @replicate@ and @slice@ functions of the @accelerate@ package.
+However the structure of slicing and replicating cannot depend on parameters.
+If you need that, you must use 'ShapeDep.backpermute' and friends.
+-}
+{-
+Some notes on the design choice:
+
+Instead of the shallow embedding implemented by the 'T' type,
+we could maintain a symbolic representation of the Slice and Replicate pattern,
+like the accelerate package does.
+We actually used that representation in former versions.
+It has however some drawbacks:
+
+* We need additional type functions that map from the pattern
+  to the source and the target shape and we need a proof,
+  that the images of these type functions are actually shapes.
+  This worked already, but was rather cumbersome.
+
+* We need a way to store and pass this pattern through the Parameter handler.
+  This yields new problems:
+  We need a wrapper type for wrapping Index, Shape, Slice, Replicate, Fold patterns.
+  Then the question is whether we use one Wrap type with a phantom parameter
+  or whether we define a Wrap type for every pattern type.
+  That is, the options are to write either
+
+  > Wrap Shape (Z:.Int:.Int)
+
+  or
+
+  > Shape (Z:.Int:.Int)
+
+  The first one seems to save us many duplicate instances of
+  Storable, MultiValue etc.
+  and it allows us easily to reuse the (:.) for all kinds of patterns.
+  However, we need a way to restrict the element type of the (:.)-list elements.
+  We can define that using variable ConstraintKinds,
+  but e.g. we are not able to add a Storable superclass constraint
+  to the instance Storable (Wrap constr).
+  That is, we are left with the second option
+  and had to define a lot of similar Storable, MultiValue instances.
+-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+module Data.Array.Knead.Symbolic.Slice (
+   T,
+   Cubic,
+   apply,
+   passAny,
+   pass,
+   pick,
+   pickFst,
+   pickSnd,
+   extrude,
+   extrudeFst,
+   extrudeSnd,
+   transpose,
+   (Core.$:.),
+
+   id,
+   first,
+   second,
+   compose,
+   ) where
+
+import qualified Data.Array.Knead.Symbolic.ShapeDependent as ShapeDep
+import qualified Data.Array.Knead.Symbolic.Private as Core
+
+import qualified Data.Array.Knead.Shape.Cubic.Int as Index
+import qualified Data.Array.Knead.Shape.Cubic as Cubic
+import qualified Data.Array.Knead.Shape as Shape
+import qualified Data.Array.Knead.Expression as Expr
+import Data.Array.Knead.Shape.Cubic ((#:.), (:.)((:.)), )
+import Data.Array.Knead.Expression (Exp, )
+
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import LLVM.Extra.Multi.Value (atom, )
+
+import qualified Type.Data.Num.Unary as Unary
+
+import qualified Prelude as P
+import Prelude hiding (id, zipWith, zipWith3, zip, zip3, replicate, )
+
+
+
+{-
+This data type is almost identical to Core.Array.
+The only difference is,
+that the shape @sh1@ in T can depend on another shape @sh0@.
+-}
+data T sh0 sh1 =
+   forall ix0 ix1.
+   (Shape.Index sh0 ~ ix0, Shape.Index sh1 ~ ix1) =>
+   Cons
+      (Exp sh0 -> Exp sh1)
+      (Exp ix1 -> Exp ix0)
+
+{- |
+This is essentially a 'ShapeDep.backpermute'.
+-}
+apply ::
+   (Core.C array, Shape.C sh0, Shape.C sh1, MultiValue.C a) =>
+   T sh0 sh1 ->
+   array sh0 a ->
+   array sh1 a
+apply (Cons fsh fix) =
+   ShapeDep.backpermute fsh fix
+
+
+pickFst :: Exp (Shape.Index n) -> T (n,sh) sh
+pickFst i = Cons Expr.snd (Expr.zip i)
+
+pickSnd :: Exp (Shape.Index n) -> T (sh,n) sh
+pickSnd i = Cons Expr.fst (flip Expr.zip i)
+
+{- |
+Extrusion has the potential to do duplicate work.
+Only use it to add dimensions of size 1, e.g. numeric 1 or unit @()@
+or to duplicate slices of physical arrays.
+-}
+extrudeFst :: Exp n -> T sh (n,sh)
+extrudeFst n = Cons (Expr.zip n) Expr.snd
+
+extrudeSnd :: Exp n -> T sh (sh,n)
+extrudeSnd n = Cons (flip Expr.zip n) Expr.fst
+
+transpose :: T (sh0,sh1) (sh1,sh0)
+transpose = Cons Expr.swap Expr.swap
+
+
+-- Arrow combinators
+
+id :: T sh sh
+id = Cons P.id P.id
+
+first :: T sh0 sh1 -> T (sh0,sh) (sh1,sh)
+first (Cons fsh fix) = Cons (Expr.mapFst fsh) (Expr.mapFst fix)
+
+second :: T sh0 sh1 -> T (sh,sh0) (sh,sh1)
+second (Cons fsh fix) = Cons (Expr.mapSnd fsh) (Expr.mapSnd fix)
+
+infixr 1 `compose`
+
+compose :: T sh0 sh1 -> T sh1 sh2 -> T sh0 sh2
+compose (Cons fshA fixA) (Cons fshB fixB) = Cons (fshB . fshA) (fixA . fixB)
+
+
+type Cubic rank0 rank1 = T (Cubic.Shape rank0) (Cubic.Shape rank1)
+
+{- |
+Like @Any@ in @accelerate@.
+-}
+passAny :: Cubic rank rank
+passAny = Cons P.id P.id
+
+{- |
+Like @All@ in @accelerate@.
+-}
+pass ::
+   (Unary.Natural rank0, Unary.Natural rank1) =>
+   Cubic rank0 rank1 ->
+   Cubic (Unary.Succ rank0) (Unary.Succ rank1)
+pass (Cons fsh fix) =
+   Cons
+      (Expr.modify (atom:.atom) $ \(sh:.s) -> fsh sh :. s)
+      (Expr.modify (atom:.atom) $ \(ix:.i) -> fix ix :. i)
+
+{- |
+Like @Int@ in @accelerate/slice@.
+-}
+pick ::
+   (Unary.Natural rank0, Unary.Natural rank1) =>
+   Exp Index.Int ->
+   Cubic rank0 rank1 ->
+   Cubic (Unary.Succ rank0) rank1
+pick i (Cons fsh fix) =
+   Cons
+      (fsh . Cubic.tail)
+      (\ix -> fix ix #:. i)
+
+{- |
+Like @Int@ in @accelerate/replicate@.
+-}
+extrude ::
+   (Unary.Natural rank0, Unary.Natural rank1) =>
+   Exp Index.Int ->
+   Cubic rank0 rank1 ->
+   Cubic rank0 (Unary.Succ rank1)
+extrude n (Cons fsh fix) =
+   Cons
+      (\sh -> fsh sh #:. n)
+      (fix . Cubic.tail)
+
+
+instance Core.Process (T sh0 sh1) where
diff --git a/test/Test/Array.hs b/test/Test/Array.hs
--- a/test/Test/Array.hs
+++ b/test/Test/Array.hs
@@ -1,16 +1,16 @@
 module Test.Array where
 
-import qualified Data.Array.Knead.Parameterized.Render as Render
-import qualified Data.Array.Knead.Simple.Symbolic as Symb
-import qualified Data.Array.Knead.Simple.Slice as Slice
+import qualified Data.Array.Knead.Symbolic.Render as Render
+import qualified Data.Array.Knead.Symbolic as Symb
+import qualified Data.Array.Knead.Symbolic.Slice as Slice
 import qualified Data.Array.Knead.Expression as Expr
 import qualified Data.Array.Knead.Shape as Shape
 import qualified Data.Array.Comfort.Storable as Array
 import qualified Data.Array.Comfort.Shape as ComfortShape
 import Data.Array.Comfort.Storable (Array)
 
-import qualified LLVM.Extra.Storable as Storable
-import qualified LLVM.Extra.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value.Storable as Storable
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
 import qualified LLVM.Extra.Multi.Value as MultiValue
 
 import qualified LLVM.Core as LLVM
@@ -71,8 +71,8 @@
 columnPred x y  =  Array.toList y == foldl1 (zipWith (+)) (getRows x)
 
 run ::
-   (Shape.C sh0, Marshal.MV sh0, Show sh0,
-    Shape.C sh1, Marshal.MV sh1, Show sh1,
+   (Shape.C sh0, Marshal.C sh0, Show sh0,
+    Shape.C sh1, Marshal.C sh1, Show sh1,
     Show a, Num a, Eq a, Storable.C a) =>
    QC.Gen (Array sh0 a) ->
    (Symb.Array sh0 a -> Symb.Array sh1 a) ->
