Numpy verfügt in seinem Array-Zugriffsoperator über eine ausgefeilte Indizierung/Slicing/Stepping-Funktionalität. Siehe auch: http://docs.scipy.org/doc/numpy/reference/arrays.indexing.htmlReplizieren von Numpys Advanced Indexing/Slicing in Haskell
Während ich mit Haskell experimentierte, dachte ich, es wäre lehrreich, eine Teilmenge dieser Indizierungsfunktionalität zu replizieren. Insbesondere ist es „Tupel Auswahlobjekte“ oder n-dimensionale Projektion“(https://en.wikipedia.org/wiki/Projection_%28relational_algebra%29)
Grundsätzlich können Sie tun:.
two_d_array[0:1:1, 0:4:2]
Und dies wird Ihnen die erste Zeile trat um 1 die ersten 2 Spalten mit abgestuften von 2 (Überspringen 1 Spalte).
mit anderen Worten kann es einen originellen 2-dimensionalen Array in einen kleineren 2-dimensionalen Array projiziert. Das Ergebnis bleibt als 2-dimensionales Array.
Also hier ist, was habe ich versucht, in Haskell
Die Art einer solchen Funktion sollte so etwas wie:
(!!!) :: (Functor f) => f a -> [(Int, Int, Int)] -> f a
So sehen Sie könnte so etwas wie:
three_d_tensor !!! [(s1,e1,st1), (s2,e2,st2), (s3,e3,st3)]
Wo sx, ex, STX Start sind, Ende, Schritt sind.
Das Beispiel sollte die ursprüngliche Tensor in einen kleineren Tensor, mit der ersten Dimension von s1 to e1, stepping by st1
, zweiter Dimension von s2 to e2, stepping by st2
beschränkt beschränkt Projekt ... usw.
Also hier ist, was ich habe:
slicing from to xs = take (to - from + 1) (drop from xs)
stepping n = map head . takeWhile (not . null) . iterate (drop n)
(!!!) tensor ((start, end, step):tail) =
project (stepSlice start end step tensor) tail map
where
project tensor ((start, end, step):tail) projection =
project (projection (stepSlice start end step) tensor) tail (projection . map)
project tensor [] _ =
tensor
stepSlice start end step tensor =
((stepping step) . (slicing start end)) tensor
Das obige funktioniert aufgrund eines Problems der "polymorphen Rekursion" nicht. Grundsätzlich kann ich nicht unendlich die map
Funktion verfassen, der spezifische Ausdruck, der das tut, ist das (projection . map)
. Wenn diese Art von polymorpher Rekursion möglich wäre, glaube ich, dass es funktionieren würde. Aber ich bin offen für alternative Implementierungen, die keine polymorphe Rekursion beinhalten.
Ich habe dieses Problem untersucht und haben immer noch zu kurz kommt:
- https://byorgey.wordpress.com/2007/08/16/mapping-over-a-nested-functor/
- http://okmij.org/ftp/Haskell/typecast.html#deepest-functor
- Haskell Polymorphic Recursion with Composed Maps causes Infinite Type Error
_Tensors sind nicht functors_ (verschachtelt oder nicht). Ja, es funktioniert manchmal so, so zu tun, und [linear] (http://hackage.haskell.org/package/linear) tut es, aber das ist eine Sache, wo EKmett es falsch gemacht hat, IMO. - Benötigen Sie wirklich Laufzeit-variable Ränge? – leftaroundabout
Beachten Sie, dass Sie ** polymorphe Rekursion ** verwenden können, vorausgesetzt, dass 1) der Typ, den die Funktion haben würde, tatsächlich syntaktisch ausdrückbar ist und 2) Sie eine explizite Typ-Signatur bereitstellen. – Bakuriu
Ich weiß nicht, ob sich das auf beide bezieht, aber sie scheinen ziemlich interessant zu sein: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/syntax-extns.html#generalised-list-comprehensions und https://hackage.haskell.org/package/DSH – dfeuer