a[i]

a

auto

arr

Int

arr :: forall a . [E Int] -> E (forall v . [E Int] -> E' v a)

atest = do { a <- arr[2]; a[1] =: a[0] + 1; }

arr

arr [s] = do s' <- runE s a <- newArray (0, s' - 1) undefined :: IO (IOArray Int a) let ix [i] = runE i return (\ is -> V (ix is >>= readArray a) (\ x -> ix is >>= \ i -> writeArray a i x))

arr

V

arr ss = do ss' <- mapM runE ss let sz = product ss' ix is = do is' <- mapM runE is when (length is' /= length ss') $ error "wrong number of indicies" return $ foldr (\ (i, s) r -> r * s + i) 0 (zip is' ss') a <- newArray (0, product ss' - 1) undefined :: IO (IOArray Int a) return (\ is -> V (ix is >>= readArray a) (\ x -> ix is >>= \ i -> writeArray a i x))

After doing my little C-like DSEL in Haskell I started wondering if you could do arrays that look like C arrays too. It turns out you can, but I can't figure out a way to make it safe from certain runtime errors. Array indexing in C is written, and this is legal syntax in Haskell too, so we're off to a good start. But to make it work we needto be a function that takes a list and returns something. What should it return? It must be something that is both an l-value and an r-value. Just as I had a functionto create a local variable, I'll have a functionto make a local array. It will take the size of the array and then return a function that takes the index. For simplicity I'll make the index be anSo now this type checksNow we just need the body ofThefunction takes a list with one element, the size, and allocates an array (indexed from 0) with this size. It then returns a function that expects a singleton list with an index and returns theconstructor which I used for variables. For multidimensional arrays we can extend the arr function.The problem with both these definitions is that the number of indicies is checked dynamically rather than statically. To do it statically we'd have to be able to overload the syntax for list literals to use a type that keeps track of the number of elements.

Labels: Haskell