{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveTraversable #-}
import Control.Comonad
import Data.Functor.Reverse
import Data.List (unfoldr)
Zuerst einige Kontext (ha ha). Ich habe eine zipper über nicht leere Listen.Comonadisch finden alle Möglichkeiten, auf ein Gitter zu konzentrieren
Sie können in beide Richtungen entlang des Reißverschlusses treten, aber Sie könnten vom Ende fallen.
fwd, bwd :: LZipper a -> Maybe (LZipper a)
fwd (LZipper _ _ []) = Nothing
fwd (LZipper (Reverse xs) e (y:ys)) = Just $ LZipper (Reverse (e:xs)) y ys
bwd (LZipper (Reverse []) _ _) = Nothing
bwd (LZipper (Reverse (x:xs)) e ys) = Just $ LZipper (Reverse xs) x (e:ys)
einen Reißverschluss Duplizierung zeigt Ihnen alle Möglichkeiten, wie man es, mit dem Fokus auf den Weg, um es Sie suchen zur Zeit aussehen könnte.
instance Comonad LZipper where
extract (LZipper _ x _) = x
duplicate z = LZipper (Reverse $ unfoldr (step bwd) z) z (unfoldr (step fwd) z)
where step move = fmap (\y -> (y, y)) . move
Zum Beispiel:
ghci> duplicate (mkZipper 'a' "bc")
LZipper (Reverse [])
(LZipper (Reverse "") 'a' "bc")
[LZipper (Reverse "a") 'b' "c",LZipper (Reverse "ba") 'c' ""]
-- Abc -> *Abc* aBc abC
ghci> fmap duplicate (fwd $ mkZipper 'a' "bc")
Just (LZipper (Reverse [LZipper (Reverse "") 'a' "bc"])
(LZipper (Reverse "a") 'b' "c")
[LZipper (Reverse "ba") 'c' ""])
-- aBc -> Abc *aBc* abC
(Ich bin mit Kapitellen und Sternchen in den Mittelpunkt des Reißverschlusses, um anzuzeigen.)
Ich versuche, mit zwei zu arbeiten Raster mit einem Fokus, dargestellt als Reißverschluß. Jeder innere Reißverschluss ist eine Reihe des Gitters. Mein Endziel ist es, Wege durch ein Raster zu finden, indem ich von Nachbarn zu Nachbarn hüpfe.
Beim Verschieben durch das Raster bleibt die Invariante erhalten, dass alle Zeilen auf denselben Index ausgerichtet sind. Dies macht es einfach, sich auf einen Ihrer Nachbarn zu konzentrieren.
type Grid a = LZipper (LZipper a)
up, down, left, right :: Grid a -> Maybe (Grid a)
up = bwd
down = fwd
left = traverse bwd
right = traverse fwd
extractGrid :: Grid a -> a
extractGrid = extract . extract
mkGrid :: (a, [a]) -> [(a, [a])] -> Grid a
mkGrid (x, xs) xss = mkZipper (mkZipper x xs) $ map (uncurry mkZipper) xss
Beispiele:
ghci> let myGrid = mkGrid ('a', "bc") [('d', "ef"), ('g', "hi")]
ghci> myGrid
LZipper (Reverse [])
(LZipper (Reverse "") 'a' "bc")
[LZipper (Reverse "") 'd' "ef",LZipper (Reverse "") 'g' "hi"]
-- +-------+
-- | A b c |
-- | d e f |
-- | g h i |
-- +-------+
ghci> return myGrid >>= right >>= down
Just (LZipper (Reverse [LZipper (Reverse "a") 'b' "c"])
(LZipper (Reverse "d") 'e' "f")
[LZipper (Reverse "g") 'h' "i"])
-- +-------+
-- | a b c |
-- | d E f |
-- | g h i |
-- +-------+
Was ich will, ist das Äquivalent von LZipper
‚s duplicate
für Grids: eine Funktion, die ein Gitter nimmt und ein Gitter von allen Möglichkeiten, wie Sie an das Netz aussehen könnte , mit dem Fokus auf die aktuelle Weise, die Sie es betrachten.
duplicateGrid :: Grid a -> Grid (Grid a)
Was ich erwarte:
duplicateGrid myGrid
+-------------------------------+
| ********* +-------+ +-------+ |
| * A b c * | a B c | | a b C | |
| * d e f * | d e f | | d e f | |
| * g h i * | g h i | | g h i | |
| ********* +-------+ +-------+ |
| +-------+ +-------+ +-------+ |
| | a b c | | a b c | | a b c | |
| | D e f | | d E f | | d e F | |
| | g h i | | g h i | | g h i | |
| +-------+ +-------+ +-------+ |
| +-------+ +-------+ +-------+ |
| | a b c | | a b c | | a b c | |
| | d e f | | d e f | | d e f | |
| | G h i | | g H i | | g h I | |
| +-------+ +-------+ +-------+ |
+-------------------------------+
Ich versuchte duplicateGrid = duplicate . duplicate
. Dies hat den richtigen Typen, aber (unter der Annahme, dass ich den show
Ausgang richtig interpretiert, die ich wahrscheinlich nicht) es gibt nur ich irgendwo auf der ersten Spalte fokussiert Grids:
(duplicate . duplicate) myGrid
+-------------------------------+
| ********* +-------+ +-------+ |
| * A b c * | a b c | | a b c | |
| * d e f * | D e f | | d e f | |
| * g h i * | g h i | | G h i | |
| ********* +-------+ +-------+ |
| +-------+ +-------+ +-------+ |
| | A b c | | a b c | | a b c | |
| | d e f | | D e f | | d e f | |
| | g h i | | g h i | | G h i | |
| +-------+ +-------+ +-------+ |
| +-------+ +-------+ +-------+ |
| | A b c | | a b c | | a b c | |
| | d e f | | D e f | | d e f | |
| | g h i | | g h i | | G h i | |
| +-------+ +-------+ +-------+ |
+-------------------------------+
Ich habe auch versucht duplicateGrid = duplicate . fmap duplicate
. Unter der Annahme, noch einmal, dass ich von der Interpretation des show
Ausgang der Lage bin, gab dies mir etwas, das sowohl die falschen Gitter enthielt und die Schwerpunkte der Reihen versetzt, so dass auch nach unten bewegen Sie sich bewegen würde zusammen:
(duplicate . fmap duplicate) myGrid
+-------------------------------+
| ********* +-------+ +-------+ |
| * A b c * | D e f | | G h i | |
| * a B c * | d E f | | g H i | |
| * a b C * | d e F | | g h I | |
| ********* +-------+ +-------+ |
| +-------+ ********* +-------+ |
| | A b c | * D e f * | G h i | |
| | a B c | * d E f * | g H i | |
| | a b C | * d e F * | g h I | |
| +-------+ ********* +-------+ |
| +-------+ +-------+ ********* |
| | A b c | | D e f | * G h i * |
| | a B c | | d E f | * g H i * |
| | a b C | | d e F | * g h I * |
| +-------+ +-------+ ********* |
+-------------------------------+
Das fühlt sich an, als ob es eine einfache Frage für diejenigen ist, die Bescheid wissen, aber es bringt meinen Kopf in Wallung. Ich nehme an, ich könnte eine Funktion, die up
, down
, left
und right
ruft Call-Handkurbeln, aber ich fühle mich wie die comonadic Maschinerie sollte es für mich tun können. Was ist die korrekte Implementierung von duplicateGrid
?
FYI, Sie könnten in anderen Bits interessiert sein. Siehe http: // stackoverflow.com/a/25572148/1477667 – dfeuer
Und [diese] (http://stackoverflow.com/questions/12963733/writing-cojoin-or-cobind-for-n-dimensional-grid-type/13100857#13100857) welche Adressen Ihre Frage speziell. Ich vermisste es irgendwie, und meine Antwort ist in ihrem Licht ziemlich überflüssig, aber zumindest hatte ich die Gelegenheit, einen Teil davon für mich selbst herauszufinden. –
@ AndrásKovács D'oh, meine Frage scheint eine genaue Kopie von diesem zu sein. Ich weiß nicht, warum ich es nicht gefunden habe, als ich gesucht habe. Ich werde das Richtige tun und dieses schließen. –