我最近在Hackage上發現了鏡頭包,並且一直試圖在一個小型測試項目中使用它,可能會變成如果我繼續努力,MUD/MUSH服務器就是一個非常遙遠的日子。我該如何處理Control.Lens.Indexed中沒有Monoid實例的at的Maybe結果
這裏是我的代碼說明我面對現在與在
{-# 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
用於訪問鍵/值容器(Data.Map.Strict在我的情況)鏡片由於房間的問題最小化版本,玩家和類似的對象在我將它們存儲在我的世界狀態類型中的代碼中作爲Ids(新類型的UUID)映射到它們的數據對象。
爲了檢索那些鏡頭,我需要處理由鏡頭返回的Maybe(萬一鑰匙不在地圖中,這是Nothing)。在我的最後一行中,我試圖通過遍歷來做到這一點,只要最終結果是Monoid的一個實例,但是通常情況並非如此。在這裏,它不是因爲playerLocation返回一個沒有Monoid實例的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'
由於含半幺羣是由僅僅是因爲橫向推廣到規模大於一,我現在不知道是否有更好的方式來處理這個問題,不要求對所有類型的語義無意義含半幺羣實例可能是容器遍歷需要包含在我想要存儲在地圖中的一個對象中。
或者我可能完全誤解了這個問題,我需要使用完全不同的相當大的鏡頭包?
如何使用'Data.Monoid'中的'First'或'Last' monoids? –