{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveTraversable #-}
import Control.Comonad
import Data.Functor.Reverse
import Data.List (unfoldr)
首先,一些上下文(哈哈)的方式。我有一個zipper在非空列表。Comonadically找出所有專注於網格
data LZipper a = LZipper (Reverse [] a) a [a]
deriving (Eq, Ord, Show, Read, Functor, Foldable, Traversable)
mkZipper :: a -> [a] -> LZipper a
mkZipper = LZipper (Reverse [])
你可以沿着拉鍊任一方向走,但你可能會掉下來。
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)
重複一個拉鍊向您顯示了所有可以看到的方式,重點介紹了當前查看方式。
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
例如:
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
(我使用的資金和星號來表示拉鍊的焦點。)
我想有兩個工作用焦點表示的三維網格,表示爲拉鍊的拉鍊。每個內部拉鍊是一排網格。我的最終目標是通過從鄰居跳轉到鄰居來尋找通過網格的路徑。
在網格中移動會保持所有行集中在同一個索引上的不變量。這使得您可以輕鬆關注您的任何鄰居。
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
例子:
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 |
-- +-------+
我要的是LZipper
的duplicate
對電網等價的:採用一個網格和生產的,你可以看一下電網的所有方式的網格功能,重點是您正在查看的目前的。
duplicateGrid :: Grid a -> Grid (Grid a)
我很期待:
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 | |
| +-------+ +-------+ +-------+ |
+-------------------------------+
我試過duplicateGrid = duplicate . duplicate
。這有正確的類型,但(假設我正確解釋show
輸出,我可能沒有),只給了我格架的地方主要集中在第一列:
(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 | |
| +-------+ +-------+ +-------+ |
+-------------------------------+
我也試過duplicateGrid = duplicate . fmap duplicate
。再次假設我能夠解釋的show
輸出的,這給了我的東西,既包含了錯誤的網格,不得不行的錯位的焦點,使得向下移動也將打動你一起:
(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 * |
| +-------+ +-------+ ********* |
+-------------------------------+
這感覺對於那些知道的人來說這將是一個簡單的問題,但它讓我感到頭暈目眩。我想我可以手動啓動一個叫做up
,down
,left
和right
的功能,但我覺得這個共同機器應該能夠爲我做到這一點。什麼是duplicateGrid
的正確實施?
FYI,您可能會對其他位感興趣。請參閱http:// stackoverflow。com/a/25572148/1477667 – dfeuer
而[this one](http://stackoverflow.com/questions/12963733/writing-cojoin-or-cobind-for-n-dimensional-grid-type/13100857#13100857)哪些地址你的問題具體。我不知何故錯過了它,而我的回答在它的光芒中是相當多餘的,但至少我有機會爲自己弄清楚它的一部分。 –
@AndrásKovácsD'oh,我的問題似乎與該問題完全相同。不知道爲什麼我在搜索時找不到它。我會做正確的事情,並關閉這一個。 –