我最近发现了Hackage镜头包,一直试图利用它现在在一家小的测试项目,如果我坚持工作,可能变成一个MUD /烂糊服务器一个非常遥远的一天。
这里是我的代码出在用于访问键/值容器的镜头,我面对现在与问题最小化版本(Data.Map.Strict在我的情况)
{-# LANGUAGE OverloadedStrings, GeneralizedNewtypeDeriving, TemplateHaskell #-}
module World where
import Control.Applicative ((<$>),(<*>), pure)
import Control.Lens
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as DM
import Data.Maybe
import Data.UUID
import Data.Text (Text)
import qualified Data.Text as T
import System.Random (Random, randomIO)
newtype RoomId = RoomId UUID deriving (Eq, Ord, Show, Read, Random)
newtype PlayerId = PlayerId UUID deriving (Eq, Ord, Show, Read, Random)
data Room =
Room { _roomId :: RoomId
, _roomName :: Text
, _roomDescription :: Text
, _roomPlayers :: [PlayerId]
} deriving (Eq, Ord, Show, Read)
makeLenses ''Room
data Player =
Player { _playerId :: PlayerId
, _playerDisplayName :: Text
, _playerLocation :: RoomId
} deriving (Eq, Ord, Show, Read)
makeLenses ''Player
data World =
World { _worldRooms :: Map RoomId Room
, _worldPlayers :: Map PlayerId Player
} deriving (Eq, Ord, Show, Read)
makeLenses ''World
mkWorld :: IO World
mkWorld = do
r1 <- Room <$> randomIO <*> (pure "The Singularity") <*> (pure "You are standing in the only place in the whole world") <*> (pure [])
p1 <- Player <$> randomIO <*> (pure "testplayer1") <*> (pure $ r1^.roomId)
let rooms = at (r1^.roomId) ?~ (set roomPlayers [p1^.playerId] r1) $ DM.empty
players = at (p1^.playerId) ?~ p1 $ DM.empty in do
return $ World rooms players
viewPlayerLocation :: World -> PlayerId -> RoomId
viewPlayerLocation world playerId=
view (worldPlayers.at playerId.traverse.playerLocation) world
由于房间,球员和相似的对象引用遍我把它们存储在我的世界状态类型的IDS(newtyped的UUID)映射到其数据对象的代码。
要检索那些镜头我需要处理也许通过在镜头莫名其妙返回(当钥匙不在地图上,这是没有)。 在我的上线我试图通过遍历只要最后的结果是含半幺群的实例,但是这不是一般的情况下,其不会进行类型检查,以做到这一点。 就在这里是不是因为playerLocation返回它没有含半幺群实例RoomId。
No instance for (Data.Monoid.Monoid RoomId)
arising from a use of `traverse'
Possible fix:
add an instance declaration for (Data.Monoid.Monoid RoomId)
In the first argument of `(.)', namely `traverse'
In the second argument of `(.)', namely `traverse . playerLocation'
In the second argument of `(.)', namely
`at playerId . traverse . playerLocation'
由于含半幺群是通过遍历只是因为横向推广到规模大于一,我现在不知道是否有更好的方式来处理这个问题,不要求对可能包含在一个我的对象我想所有类型的语义上无意义的含半幺群实例的容器要求存储在地图中。
或者,也许我在这里完全误解的问题,我需要用相当大的透镜组件的一个完全不同的位?