一个函数的类型签名是什么,它可以像 (& f %~) 和 (^.f) 一样应用,其中运算符来自 Lens 库?
What would be the type signature of a function that can be applied both like (& f %~) and (^. f) where operators are from Lens library?
我有一个函数可以从记录中获取值并将其设置到不同记录中的相同字段。
我想做的是了解它背后的机制是如何工作的
setToPercent perc basedOn toSetOn = setStat
where baseStat = basedOn ^. _func -- type is Maybe Float
percentDelta = (\a -> perc * a) <$> baseStat -- Maybe Float
setStat = toSetOn & _func %~ (\a -> (+) <$> a <*> percentDelta)
其中 _func
定义为 MyDataType -> Maybe Float
(记录语法中的默认函数。)
而且它的工作原理与我预期的一样。我想知道的是 _func
的类型签名。
我知道这里 basedOn ^. _func
, _func
会有这样的类型
Getting (f0 Float) MyDataType (f0 Float)
这里 toSetOn & _func %~ (\a -> (+) <$> a <*> percentDelta
,_func
的类型是 ASetter Weapon Weapon (f0 Float) (f0 Float)
其中数据 Weapon
和 MyDataType
基本上是具有相同构造函数的相同数据类型。
但我不确定整体类型是什么。
如果我将 setToPercent
w.r.t _func
概括为
中的函数类型会是什么
setToPercent fnToApply perc basedOn toSetOn = setStat
where baseStat = basedOn ^. fnToApply -- type is Maybe Float
percentDelta = (\a -> perc * a) <$> baseStat -- Maybe Float
setStat = toSetOn & fnToApply %~ (\a -> (+) <$> a <*> percentDelta)
有趣的问题!
I know here basedOn ^. _func
, _func
would have the type Getting (f0 Float) MyDataType (f0 Float)
and here toSetOn & _func %~ (\a -> (+) <$> a <*> percentDelta
, _func
would have the type ASetter Weapon Weapon (f0 Float) (f0 Float)
因此,非正式地,_func
既是 getter 又是 setter。查看 Oleg Grenrus 在 the lens homepage on Hackage or the one on the Glassery blogpost 上的图表,getters 和 setters 的“最不共同的祖先”是透镜。
镜头库提出了至少两种镜头表示形式,一种是多态的 Lens' Weapon (f0 Float)
(定义中包含 forall
),另一种是单态的 ALens' Weapon (f0 Float)
(取代了 forall
与一个具体的函子)。
由于我们希望此处 _func
自动专门化为 ASetter
和 Getting
,一种直接的方法是使用多态方法(这需要 RankNTypes
如果 _func
是一个参数而不是顶层绑定)。
_func :: Lens' Weapon (f0 Float) -- Polymorphic
-- specializes to
:: Getting (f0 Float) Weapon (f0 Float)
:: ASetter' Weapon (f0 Float)
还有另一种使用单态版本的方法。当 _func
是函数参数时,我发现这更符合习惯,因为它使调用者更容易传递合适的参数。但是,当我们实际使用它时,我们必须明确地概括 _func
。
_func :: ALens' Weapon (f0 Float) -- Monomorphic
cloneLens _func :: Lens' Weapon (f0 Float) -- Polymorphic again
-- The ALens' type synonym usually appears in argument position
myFun :: ALens' Foo Bar -> MyResult
myFun _func = ...
-- Example usage
basedOn ^. cloneLens _func
toSetOn & cloneLens _func %~ ...
我有一个函数可以从记录中获取值并将其设置到不同记录中的相同字段。
我想做的是了解它背后的机制是如何工作的
setToPercent perc basedOn toSetOn = setStat
where baseStat = basedOn ^. _func -- type is Maybe Float
percentDelta = (\a -> perc * a) <$> baseStat -- Maybe Float
setStat = toSetOn & _func %~ (\a -> (+) <$> a <*> percentDelta)
其中 _func
定义为 MyDataType -> Maybe Float
(记录语法中的默认函数。)
而且它的工作原理与我预期的一样。我想知道的是 _func
的类型签名。
我知道这里 basedOn ^. _func
, _func
会有这样的类型
Getting (f0 Float) MyDataType (f0 Float)
这里 toSetOn & _func %~ (\a -> (+) <$> a <*> percentDelta
,_func
的类型是 ASetter Weapon Weapon (f0 Float) (f0 Float)
其中数据 Weapon
和 MyDataType
基本上是具有相同构造函数的相同数据类型。
但我不确定整体类型是什么。
如果我将 setToPercent
w.r.t _func
概括为
setToPercent fnToApply perc basedOn toSetOn = setStat
where baseStat = basedOn ^. fnToApply -- type is Maybe Float
percentDelta = (\a -> perc * a) <$> baseStat -- Maybe Float
setStat = toSetOn & fnToApply %~ (\a -> (+) <$> a <*> percentDelta)
有趣的问题!
I know here
basedOn ^. _func
,_func
would have the typeGetting (f0 Float) MyDataType (f0 Float)
and here
toSetOn & _func %~ (\a -> (+) <$> a <*> percentDelta
,_func
would have the typeASetter Weapon Weapon (f0 Float) (f0 Float)
因此,非正式地,_func
既是 getter 又是 setter。查看 Oleg Grenrus 在 the lens homepage on Hackage or the one on the Glassery blogpost 上的图表,getters 和 setters 的“最不共同的祖先”是透镜。
镜头库提出了至少两种镜头表示形式,一种是多态的 Lens' Weapon (f0 Float)
(定义中包含 forall
),另一种是单态的 ALens' Weapon (f0 Float)
(取代了 forall
与一个具体的函子)。
由于我们希望此处 _func
自动专门化为 ASetter
和 Getting
,一种直接的方法是使用多态方法(这需要 RankNTypes
如果 _func
是一个参数而不是顶层绑定)。
_func :: Lens' Weapon (f0 Float) -- Polymorphic
-- specializes to
:: Getting (f0 Float) Weapon (f0 Float)
:: ASetter' Weapon (f0 Float)
还有另一种使用单态版本的方法。当 _func
是函数参数时,我发现这更符合习惯,因为它使调用者更容易传递合适的参数。但是,当我们实际使用它时,我们必须明确地概括 _func
。
_func :: ALens' Weapon (f0 Float) -- Monomorphic
cloneLens _func :: Lens' Weapon (f0 Float) -- Polymorphic again
-- The ALens' type synonym usually appears in argument position
myFun :: ALens' Foo Bar -> MyResult
myFun _func = ...
-- Example usage
basedOn ^. cloneLens _func
toSetOn & cloneLens _func %~ ...