Haskell 镜头变焦模糊变量

Haskell 镜头变焦模糊变量,haskell,haskell-lens,Haskell,Haskell Lens,我在使用Control.Lens提供的zoom功能时遇到困难。使用我定制的monad transformerHearthMonad,我无法理解如何满足GHC的“模棱两可类型”投诉 有问题的代码在提款卡中 我怎样才能解决这个问题?我是否必须创建自己的自定义缩放操作符来处理炉膛m中的单子m {-#语言约束种类} {-#语言泛化newtypedering} {-#语言MultiParamTypeClasses} {-#语言等级} {-#语言模板haskell} 模块引擎空间在哪里 ---------

我在使用
Control.Lens
提供的
zoom
功能时遇到困难。使用我定制的monad transformer
HearthMonad
,我无法理解如何满足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)