Haskell 镜头变焦模糊变量
我在使用Haskell 镜头变焦模糊变量,haskell,haskell-lens,Haskell,Haskell Lens,我在使用Control.Lens提供的zoom功能时遇到困难。使用我定制的monad transformerHearthMonad,我无法理解如何满足GHC的“模棱两可类型”投诉 有问题的代码在提款卡中 我怎样才能解决这个问题?我是否必须创建自己的自定义缩放操作符来处理炉膛m中的单子m {-#语言约束种类} {-#语言泛化newtypedering} {-#语言MultiParamTypeClasses} {-#语言等级} {-#语言模板haskell} 模块引擎空间在哪里 ---------
Control.Lens
提供的zoom
功能时遇到困难。使用我定制的monad transformerHearthMonad
,我无法理解如何满足GHC的“模棱两可类型”投诉
有问题的代码在提款卡中
我怎样才能解决这个问题?我是否必须创建自己的自定义缩放操作符来处理炉膛m
中的单子m
{-#语言约束种类}
{-#语言泛化newtypedering}
{-#语言MultiParamTypeClasses}
{-#语言等级}
{-#语言模板haskell}
模块引擎空间在哪里
--------------------------------------------------------------------------------
导入控制
进口管制.镜头
进口控制单体状态
导入数据。列表
导入数据,也许吧
--------------------------------------------------------------------------------
键入PlayerHandle=String
数据卡=卡串
推导(显示、等式、Ord)
数据播放器{
_playerHandle::playerHandle,
_手::[卡片]
}推导(显示、等式、Ord)
makelens“播放器
数据游戏状态=游戏状态{
_玩家::[玩家]
}推导(显示、等式、Ord)
游戏状态
新型炉缸m a=炉缸{
unHearth::StateT GameState m a
}派生(函子、应用程序、单子、单子状态配子状态、单子状态、单子状态、单子状态)
类型HearthMonad=MonadIO
炉床::(炉床主调m)=>m()
runHearth=evalStateT(un接地runGame)mkGameState
mkGameState::GameState
mkGameState=GameState{{u gamePlayers=map mkPlayer[“Bob”,“Joe”]}
mkPlayer::PlayerHandle->Player
mkPlayer handle=Player{{u Player handle=handle,{u hand=[]}
runGame::(炉边m)=>炉边m()
runGame=do
卡镜头的游戏状态玩家
getPlayer句柄f st=fmap put'get'
哪里
玩家=游戏玩家
放球员=放球员
g p=案例p^。playerHandle==游戏手柄
真->玩家
假->p
集合内玩家(地图g玩家)st
从$find(\p->p^.playerHandle==handle)玩家中获取'=f$
抽卡::(炉边m)=>玩家手柄->炉边m卡
抽卡手柄=do
让卡片=卡片“雪人”
--getPlayer handle.hand=[卡]
缩放(getPlayer手柄)$hand=[卡]
回程卡
EngineZoom.hs:86:5:
无法推断(Control.Lens.Internal.Zoom.zomed)(炉膛m)
~Control.Lens.Internal.Zoom.Zoomed m0)
从上下文(HearthMonad m)
由的类型签名绑定
drawCard::HearthMonad m=>玩家手柄->Hearth m卡
在引擎室。hs:82:13-60
注意:`Control.Lens.Internal.Zoom.Zoomed'是一个类型函数,可能不是内射函数
类型变量“m0”不明确
相关绑定包括
抽卡::玩家手柄->壁炉m卡
(在引擎室装订。hs:83:1)
在表达式中:缩放(getPlayer句柄)
在“do”块的stmt中:
缩放(getPlayer手柄)$hand=[卡]
在表达式中:
让卡片=卡片“雪人”;
缩放(getPlayer手柄)$hand=[卡];
回程卡}
问题是您的新类型只能保存一种状态,即游戏状态
。变焦本质上改变了镜头目标的状态,但由于灶台
不能将播放器
作为一种状态,因此变焦(getPlayer handle)
不能与灶台
一起使用
简单的解决方案是用type-Hearth=StateT-GameState
替换新类型,然后缩放工作。如果需要新类型,则需要将状态参数化,下面是一个示例:
import Control.Lens.Internal.Zoom
newtype HearthS s m a = Hearth {
unHearth :: StateT s m a
} deriving (Functor, Applicative, Monad, MonadState s, MonadIO, MonadTrans)
type Hearth = HearthS GameState
type instance Zoomed (HearthS s m) = Focusing m
instance Monad z => Zoom (HearthS s z) (HearthS t z) s t where
zoom l (Hearth m) = Hearth (zoom l m)
我认为这是不对的。OP的问题是,他一开始没有任何通过Zoom的实例,我们可以通过编写实例来解决这个问题,并且没有必要泛化状态<代码>缩放(壁炉m)=聚焦m和
实例单子m=>缩放(壁炉m)(壁炉m)游戏状态游戏状态在这里也很好。Zoom
中的s
和t
参数指的是monad transformer的新旧状态类型,而不是可以缩放的镜头类型。@AndrásKovács您可以编写该实例,但我无法使其工作。hand=[card]
的类型是什么?在我的解决方案中,它是HearthS Player m()
。由于函数依赖关系,您也无法编写Zoom(StateT t z)(Hearth z)t GameState
实例。您可以执行Zoom(HearthS t z)(Hearth z)t GameState
,其中HearthS
和Hearth
都是新类型,但这似乎是一个糟糕的解决方案。
EngineZoom.hs:86:5:
Could not deduce (Control.Lens.Internal.Zoom.Zoomed (Hearth m)
~ Control.Lens.Internal.Zoom.Zoomed m0)
from the context (HearthMonad m)
bound by the type signature for
drawCard :: HearthMonad m => PlayerHandle -> Hearth m Card
at EngineZoom.hs:82:13-60
NB: `Control.Lens.Internal.Zoom.Zoomed' is a type function, and may not be injective
The type variable `m0' is ambiguous
Relevant bindings include
drawCard :: PlayerHandle -> Hearth m Card
(bound at EngineZoom.hs:83:1)
In the expression: zoom (getPlayer handle)
In a stmt of a 'do' block:
zoom (getPlayer handle) $ hand <>= [card]
In the expression:
do { let card = Card "Yeti";
zoom (getPlayer handle) $ hand <>= [card];
return card }
import Control.Lens.Internal.Zoom
newtype HearthS s m a = Hearth {
unHearth :: StateT s m a
} deriving (Functor, Applicative, Monad, MonadState s, MonadIO, MonadTrans)
type Hearth = HearthS GameState
type instance Zoomed (HearthS s m) = Focusing m
instance Monad z => Zoom (HearthS s z) (HearthS t z) s t where
zoom l (Hearth m) = Hearth (zoom l m)