reddit に関するこの 2 つのコメントに触発されて、「レンズ化されたエンティティ システム」の作成に着手しました。基本的な考え方はLens' Entity Value
レンズを持つことですが、副作用のある sAction
を作成することはありますが、何もないか、組み合わせることはありません。Getter
Setter
LensM'
おそらく次のようなものを使用Lens' (Entity, State) Value
できますが、これをより良い方法で行う方法 (および場合) に興味があります。
わかりました...ここに私が得たものがあります:
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import qualified Data.Map as M
import Control.Monad.State
import Control.Lens
newtype Entity = Entity { unEntity :: Int }
deriving (Show, Eq, Ord, Enum)
type Address = String
type Name = String
data EntitySystem = EntitySystem {
_nextEntity :: Entity,
_addresses :: M.Map Entity Address,
_names :: M.Map Entity Name
} deriving (Show, Eq, Ord)
makeLenses ''EntitySystem
newEntry :: Name -> Address -> State EntitySystem Entity
newEntry name addr = do
ne <- nextEntity <<%= succ
addresses.at ne ?= addr
names.at ne ?= name
return ne
entityAddress e = addresses . at e
entityName e = names . at e
基本的に私は使用できますentityAddress entity
(これはタイプである必要がありますがEntity -> Lens' EntitySystem Address
、ghcは不平を言っています)。しかし、これは「レンズっぽい」とは感じません。私が望んでいるentityAddress :: Lens' Entity Address
のは、エンティティ システムのすべてのステートフルな処理がユーザーから隠されているようなものです。