HaskellからCの配列を利用する

ITプロに「本物のプログラマHaskellを使う」が連載されていますが、今回の記事はは「第58回 Cの配列をHaskellで利用する」です。

丁度配列を使いたいところでした。しかし、Array 型は、参照は O(1) で出来ますが、 更新には O(n) かかります。
そこで、記事を写経しながら、Cの配列を使う練習をしてみました。

  • Array.hs
-- $ ghc -Wall carray.h carray.c Array.hs
import Foreign.C.Types       ( CInt(..) )
import Foreign.Marshal.Array
import Foreign.Ptr           ( Ptr(..) )

main :: IO ()
main = do
    let xs :: [CInt]
        xs  = [0..9]
        len = length xs
    ys <- withArray xs $ \carr -> do
              cUpdateArray carr 0 (fromIntegral 123)
              cUpdateArray carr 4 (fromIntegral 999)
              print =<< cGetArrayElem carr 0  -- > 123
              print =<< cGetArrayElem carr 1  -- > 1
              print =<< cGetArrayElem carr 2  -- > 2
              print =<< cGetArrayElem carr 3  -- > 3
              print =<< cGetArrayElem carr 4  -- > 999
              peekArray len carr
    print ys  -- > [123,1,2,3,999,5,6,7,8,9]

foreign import ccall "updateArray"  cUpdateArray  :: Ptr CInt -> CInt -> CInt -> IO ()
foreign import ccall "getArrayElem" cGetArrayElem :: Ptr CInt -> CInt -> IO CInt
  • carray.h
void updateArray ( int*, int, int );
int  getArrayElem ( int *, int);
  • carray.c
#include "carray.h"

void updateArray ( int *xs, int p, int x) { xs[p] = x;}

int  getArrayElem ( int *xs, int p) { return xs[p];}
$ ghc carray.h carray.c Array.hs
[1 of 1] Compiling Main             ( Array.hs, Array.o )
Linking Array.exe ...

$ ./Array
123
1
2
3
999
[123,1,2,3,999,5,6,7,8,9]