これは片道です(here is a complete Gist)。私たちはGHCのタイプレベルNat
の代わりにPeanoの数字を使用することに固執しています。
{-# LANGUAGE GADTs, PolyKinds, DataKinds, TypeOperators, FlexibleInstances, FlexibleContexts #-}
import Data.Foldable
import Text.PrettyPrint.HughesPJClass
data Nat = Z | S Nat
-- Some type synonyms that simplify uses of 'Nat'
type N0 = Z
type N1 = S N0
type N2 = S N1
type N3 = S N2
type N4 = S N3
type N5 = S N4
type N6 = S N5
type N7 = S N6
type N8 = S N7
type N9 = S N8
-- Similar to lists, but indexed over their length
data Vector (dim :: Nat) a where
Nil :: Vector Z a
(:-) :: a -> Vector n a -> Vector (S n) a
infixr 5 :-
data Tensor (dim :: [Nat]) a where
Scalar :: a -> Tensor '[] a
Tensor :: Vector d (Tensor ds a) -> Tensor (d : ds) a
これらのタイプを表示するには、我々は(すでにGHCに付属している)pretty
パッケージを使用します。
instance Foldable (Vector Z) where
foldMap f Nil = mempty
instance Foldable (Vector n) => Foldable (Vector (S n)) where
foldMap f (x :- xs) = f x `mappend` foldMap f xs
instance Foldable (Tensor '[]) where
foldMap f (Scalar x) = f x
instance (Foldable (Vector d), Foldable (Tensor ds)) => Foldable (Tensor (d : ds)) where
foldMap f (Tensor xs) = foldMap (foldMap f) xs
最後に、一部: -
instance (Foldable (Vector n), Pretty a) => Pretty (Vector n a) where
pPrint = braces . sep . punctuate (text ",") . map pPrint . toList
instance Pretty a => Pretty (Tensor '[] a) where
pPrint (Scalar x) = pPrint x
instance (Pretty (Tensor ds a), Pretty a, Foldable (Vector d)) => Pretty (Tensor (d : ds) a) where
pPrint (Tensor xs) = pPrint xs
は次にここに私たちのデータ型のFoldable
(私はPretty
インスタンスをコンパイルするためにあなたがそれを必要とするだけであるため、これを含めたよ何もここで意外な)のインスタンスでありますあなたは答えます:Applicative (Vector n)
とApplicative (Tensor ds)
はApplicative ZipList
と同じように定義できます(pure
は返さず、空のリスト - 正しい長さのリストを返します)。
instance Applicative (Vector Z) where
pure _ = Nil
Nil <*> Nil = Nil
instance Applicative (Vector n) => Applicative (Vector (S n)) where
pure x = x :- pure x
(x :- xs) <*> (y :- ys) = x y :- (xs <*> ys)
instance Applicative (Tensor '[]) where
pure = Scalar
Scalar x <*> Scalar y = Scalar (x y)
instance (Applicative (Vector d), Applicative (Tensor ds)) => Applicative (Tensor (d : ds)) where
pure x = Tensor (pure (pure x))
Tensor xs <*> Tensor ys = Tensor ((<*>) <$> xs <*> ys)
その後、GHCiの中で、あなたのzero
機能を作るために非常に簡単です:
ghci> :set -XDataKinds
ghci> zero = pure 0
ghci> pPrint (zero :: Tensor [N5,N3,N2] Integer)
{{{0, 0}, {0, 0}, {0, 0}},
{{0, 0}, {0, 0}, {0, 0}},
{{0, 0}, {0, 0}, {0, 0}},
{{0, 0}, {0, 0}, {0, 0}},
{{0, 0}, {0, 0}, {0, 0}}}
あなたは[Data.FixedList](https://hackage.haskell.org/package/に見えるかもしれませんfixed-list-0.1.6/docs/Data-FixedList.html)ライブラリを使用して、固定長のリストに応じて型を定義します。 – Redu
関連性の高いリンク:https://blog.jle.im/entry/practical-dependent-types-in-haskell-1.html https://blog.jle.im/entry/practical-dependent-types-in -haskell-2.html https://www.reddit.com/r/haskell/comments/67f4mw/naperian_tensors/また、ベクターサイズのパッケージhttp://hackage.haskell.org/package/vector-sized – danidiaz
もご覧くださいMike Izbickiの[subhask'の線形代数部分](http://hackage.haskell.org/package/subhask-0.1.1.0/docs/SubHask-Algebra-Vector.html)の仕事をチェックしてください(彼はあなたがTensorFlowの方向に行きたいなら、これは関連するかもしれません)、そして私の[linearmap-category](http://hackage.haskell.org/package/linearmapapcategory-0.3。 2.0/docs/Math-LinearMap-Category.html#g:5)(完全に基底にとらわれない方法でテンソルを定義し、_dimensions_については決して語っていませんが、_vectorスペースについては決して言及しません - これらは無限次元でもあります) – leftaroundabout