Şu an bununla oynuyordum ama bu işi yapmak için GHC'yi ikna edemedim.Bağımlı büyüklükteki dizileri n boyutlarına genellemek için?
newtype Arr1 (w :: Nat) a = Arr1 (Int -> a)
newtype Arr2 (w :: Nat) (h :: Nat) a = Arr2 (Int -> a)
ix2 :: forall w h a. (KnownNat w) => Arr2 w h a -> Int -> Int -> a
ix2 (Arr2 f) x y = f (y * w + x)
where w = fromInteger $ natVal (Proxy :: Proxy w)
sub2 :: forall w h a. (KnownNat w) => Arr2 w h a -> Int -> Arr1 w a
sub2 (Arr2 f) y = Arr1 $ \x -> f (y * w + x)
where w = fromInteger $ natVal (Proxy :: Proxy w)
mkArr2V :: forall w h a. (V.Unbox a, KnownNat w, KnownNat h) => V.Vector a -> Arr2 w h a
mkArr2V v = Arr2 $ (v V.!)
-- and so on ... errorchecking neglected
Ama şimdiki GHC versiyonları bize çok daha expressibility vermek:
Temel olarak bağımlı boy Haskell/ghc güncel sürümlerinde diziler oluşturmak için oldukça kolaydır. Temelde bunun için tek bir türünü oluşturmak için mümkün olmalıdır: Bu GHCi çalışır
newtype Mat (s :: [Nat]) a = Mat (Int -> a)
-- create array backed by vector
mkMatV :: forall s a. V.Vector a -> Mat s a
mkMatV v = Mat $ (v V.!)
:
>>> let m = mkMatV (V.fromList [1,2,3,4]) :: Mat [2,2] Double
>>> :t m
m :: Mat '[2, 2] Double
Ama diziler içine indeksleme gerçekleştirmek için nasıl emin değilim bu noktaya kadar
. Basit bir çözüm, nd ve 1d endeksleme için iki farklı fonksiyon kullanmak olacaktır. Not bu yazmaz.-- slice from nd array
(!) :: forall s ss a. (KnownNat s) => Mat (s ': ss) a -> Int -> Mat ss a
(!) (Mat f) o = Mat $ \i -> f (o*s+i)
where s = fromInteger $ natVal (Proxy :: Proxy (sum ss))
-- index into 1d array
(#) :: forall s ss a. (KnownNat s) => Mat (s ': '[]) a -> Int -> a
(#) (Mat f) o = Mat $ \i -> f o
böyle muhtemelen kullanılabilir: Z, Y, x, için endeksler vermek için gerekli olan Değil
>>> :t m ! 0
Mat [2] Double
>>> m ! 0 # 0
1
. Tercih edilen çözümüm, dizinin boyutuna bağlı olarak dönüş türünü değiştiren tek bir endeksleme işlevi sağlar. Benim bildiğim kadarıyla bu tür sınıfları kullanarak bir şekilde elde edilebilir, ancak bunu henüz anlamadım. Endeksler "doğal" x, y, z sırasına göre verilebilirse bonus puanları.
tl; dr: Yukarıda tanımlanan şekilde n boyutlu dizileri indeksleyen bir işlev istiyorum.
acaba işlevleri uzatmak ne tür düzeyinde kullanılabilir. Orada normal liste işlevlerini kullanabileceğinizi hissettim, ancak hızlı bir deneme bunu doğrulamadı. – fho