我试图找到一些comonad的实际应用,我想我会尝试看看我是否可以将经典的Wumpus世界表示为comonad。
我想用这段代码让 Wumpus 在世界上左右移动,清理脏瓷砖,避免坑。似乎唯一有用的comonad函数是提取(获取当前图块),并且无法使用移动和清洁图块来使用扩展或复制。
我不确定comonads 是否合适,但我看过一个演讲(Dominic Orchard: A Notation for Comonads),其中comonads 用于在二维矩阵中对光标进行建模。
如果comonad 是代表Wumpus 世界的好方法,您能否说明我的代码哪里出错了?如果错了,你能建议一个简单的comonads应用吗?
module Wumpus where
-- Incomplete model of a world inhabited by a Wumpus who likes a nice
-- tidy world but does not like falling in pits.
import Control.Comonad
-- The Wumpus world is made up of tiles that can be in one of three
-- states.
data Tile = Clean | Dirty | Pit
deriving (Show, Eq)
-- The Wumpus world is a one dimensional array partitioned into three
-- values: the tiles to the left of the Wumpus, the tile occupied by
-- the Wumpus, and the tiles to the right of the Wumpus.
data World a = World [a] a [a]
deriving (Show, Eq)
-- Applies a function to every tile in the world
instance Functor World where
fmap f (World as b cs) = World (fmap f as) (f b) (fmap f cs)
-- The Wumpus world is a Comonad
instance Comonad World where
-- get the part of the world the Wumpus currently occupies
extract (World _ b _) = b
-- not sure what this means in the Wumpus world. This type checks
-- but does not make sense to me.
extend f w@(World as b cs) = World (map world as) (f w) (map world cs)
where world v = f (World [] v [])
-- returns a world in which the Wumpus has either 1) moved one tile to
-- the left or 2) stayed in the same place if the Wumpus could not move
-- to the left.
moveLeft :: World a -> World a
moveLeft w@(World [] _ _) = w
moveLeft (World as b cs) = World (init as) (last as) (b:cs)
-- returns a world in which the Wumpus has either 1) moved one tile to
-- the right or 2) stayed in the same place if the Wumpus could not move
-- to the right.
moveRight :: World a -> World a
moveRight w@(World _ _ []) = w
moveRight (World as b cs) = World (as ++ [b]) (head cs) (tail cs)
initWorld = World [Dirty, Clean, Dirty] Dirty [Clean, Dirty, Pit]
-- cleans the current tile
cleanTile :: Tile -> Tile
cleanTile Dirty = Clean
cleanTile t = t
谢谢!