gpt4 book ai didi

haskell - 修改可扩展记录时重叠实例

转载 作者:行者123 更新时间:2023-12-02 18:16:12 26 4
gpt4 key购买 nike

我正在我的项目中尝试可扩展记录(我正在使用行类型库),但是当我想以特定方式修改记录中的某些内容时遇到问题,这会返回非常关于重叠实例和不可推论类型的可怕错误。

我想表达的是一个函数,它获取包含特定标签类型对的记录,并且可以修改该类型。但是当我尝试使用该功能时,会弹出可怕的错误。

我已将错误减少到以下示例。特别是启用 IncoherentInstances(Could not deruce: (Rec.Modify "x"[Double] r .! "x") ~ [Double]) 后的错误似乎很奇怪我,因为它就在那里说该记录包含 "x":-> [Double]。我尝试使用 f2::forall r 避免 Rec.Modify 。 (HasType aes a r) => Rec r -> Rec (r .- aes .+ aes .== b),但这会导致类似的错误。

我很想得到一些帮助来弄清楚我做错了什么,以及如何使这样的事情发挥作用。

{-# LANGUAGE DataKinds, OverloadedLabels, TypeOperators, RankNTypes,
RecordWildCards, NoMonomorphismRestriction #-}
module GoG.Temp where

import Data.Row
import qualified Data.Row.Records as Rec

type Scale' aes a = Scale aes a a
data Scale aes a b = Scale
-- f1 works great
-- f2 results in very scary errormessages
{ f1 :: forall r. (HasType aes a r) => Rec r -> Rec r
-- What I'd like to express is a function that gets a record containing a
-- specific label-type pair, and may modify that type. But when I try to
-- use that function, the scary errors pop up
, f2 :: forall r. (HasType aes a r) => Rec r -> Rec (Rec.Modify aes b r)
-- ... other fields
}

data Scales = Scales { _xScale :: Scale' "x" [Double] }

extractFromRecord :: (HasType "x" [Double] r, HasType "y" [Double] r)
=> Rec r -> ()
extractFromRecord = undefined

render :: (HasType "x" [Double] r, HasType "y" [Double] r)
=> Scales -> Rec r -> ()
-- If you replace f2 with f1 it works fine, but f2 results in the error
render Scales{..} r = extractFromRecord $ f2 _xScale r

这会导致以下错误:

    • Overlapping instances for HasType
"x" [Double] (Rec.Modify "x" [Double] r)
arising from a use of ‘extractFromRecord’
Matching instances:
instance forall k (r :: Row
k) (l :: ghc-prim-0.5.3:GHC.Types.Symbol) (a :: k).
((r .! l) ≈ a) =>
HasType l a r
-- Defined in ‘Data.Row.Internal’
There exists a (perhaps superclass) match:
from the context: (HasType "x" [Double] r, HasType "y" [Double] r)
bound by the type signature for:
render :: forall (r :: Row *).
(HasType "x" [Double] r, HasType "y" [Double] r) =>
Scales -> Rec r -> ()
at /mnt/d/University/infoafp/afp-gog/src/GoG/Temp.hs:22:1-83
(The choice depends on the instantiation of ‘r’
To pick the first instance above, use IncoherentInstances
when compiling the other instance declarations)
• In the expression: extractFromRecord $ f2 _xScale r
In an equation for ‘render’:
render Scales {..} r = extractFromRecord $ f2 _xScale r
|
23 | render Scales{..} r = extractFromRecord $ f2 _xScale r
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

或者如果我们按照建议启用 IncoherentInstances:

    • Could not deduce: (Rec.Modify "x" [Double] r .! "x") ~ [Double]
arising from a use of ‘extractFromRecord’
from the context: (HasType "x" [Double] r, HasType "y" [Double] r)
bound by the type signature for:
render :: forall (r :: Row *).
(HasType "x" [Double] r, HasType "y" [Double] r) =>
Scales -> Rec r -> ()
at /mnt/d/University/infoafp/afp-gog/src/GoG/Temp.hs:23:1-83
• In the expression: extractFromRecord $ f2 _xScale r
In an equation for ‘render’:
render Scales {..} r = extractFromRecord $ f2 _xScale r
• Relevant bindings include
r :: Rec r
(bound at /mnt/d/University/infoafp/afp-gog/src/GoG/Temp.hs:24:19)
render :: Scales -> Rec r -> ()
(bound at /mnt/d/University/infoafp/afp-gog/src/GoG/Temp.hs:24:1)
|
24 | render Scales{..} r = extractFromRecord $ f2 _xScale r
|

最佳答案

可怕的信息大多是无关紧要的。这个简化的示例将 HasType 替换为它的 (.!) 等效项,并说明了问题,我认为您已经在上面发现了这个问题:

{-# LANGUAGE DataKinds, FlexibleContexts, TypeOperators, GADTs #-}

module MyRow where

import Data.Row
import qualified Data.Row.Records as Rec

f2 :: ((r .! "x") ~ Double) => Rec r -> Rec (Rec.Modify "x" Double r)
f2 = undefined

extract :: ((r .! "x") ~ Double) => Rec r -> ()
extract = undefined

render :: ((r .! "x") ~ Double) => Rec r -> ()
render r = extract $ f2 r

此代码导致错误:无法从 (r .! "x") ~ Double< 推导出 (Modify "x"Double r .! "x") ~ Double/。这可能“显然”是正确的,但这并不意味着 GHC 可以证明这一点。

我很高兴被证明是错误的,但我认为您将被迫添加所需的显式约束。在您原来的示例中,以下类型签名(如果您省略它,GHC 能够自行推断)似乎有效:

render ::
( HasType "x" [Double] r
, HasType "x" [Double] (Rec.Modify "x" [Double] r)
, HasType "y" [Double] (Rec.Modify "x" [Double] r)
) => Scales -> Rec r -> ()
render Scales{..} r = extractFromRecord $ f2 _xScale r

除了您在示例中启用的其他扩展之外,我还必须打开 FlexibleContextsGADTs

关于haskell - 修改可扩展记录时重叠实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55435078/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com