Reputation: 55
I have been stuck on this error for quite a while. I'm not sure if I am being stupid but I cannot see where it is coming from...
The data type Settings
is defined as so:
data Settings a = Settings {
_nodeDrawFunction :: a -> Diagram B
, _dynamicHead :: Measure Double
, _dynamicThick :: Measure Double
, _directed :: Directed
, _horizontalOrientation :: Maybe Bool
, _layerSpacing :: Maybe Double
, _nodeSpacing :: Maybe Double
, _graphPadding :: Maybe Double
, _colF :: Maybe (Int -> Colour Double)
, _bgOp :: Maybe Double
, _initPos :: Maybe Int
}
And makeLenses ''Settings
is used to create lenses for each record. The default for _drawNodeFunction
is drawDefaultNode
.
When I create a function overwriting some of these values using Lens setters it works fine, for example:
test1 :: (Show a) => Graph a -> Settings a
test1 g = def & bgOp .~ Just 1
Which works as expected. The type of Graph
is from the library algebraic-graphs.
If I try to set nodeDrawFunction
, for example with:
test2 :: (Show a) => Graph a -> Settings a
test2 g = def & nodeDrawFunction .~ drawDefaultNode
& bgOp .~ Just 1
The following error is produced:
Could not deduce (Show a10) arising from a use of ‘def’
from the context: Show a
bound by the type signature for:
test2 :: forall a. Show a => Graph a -> Settings a
at Visualise/Hierarchical.hs:78:1-42
The type variable ‘a10’ is ambiguous
These potential instances exist:
instance Show n => Show (Duration n) -- Defined in ‘Data.Active’
instance Show n => Show (Era n) -- Defined in ‘Data.Active’
instance Show n => Show (Time n) -- Defined in ‘Data.Active’
...plus 74 others
...plus 264 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the first argument of ‘(&)’, namely ‘def’
In the first argument of ‘(&)’, namely
‘def & nodeDrawFunction .~ drawDefaultNode’
In the expression:
def & nodeDrawFunction .~ drawDefaultNode & bgOp .~ Just 1
Even if I try to set nodeDrawFunction
to the default value (as well as any other valid function).
Any help would be much appreciated, thanks!
Upvotes: 0
Views: 169
Reputation: 3081
You probably intend that def
and def & nodeDrawFunction .~ drawDefaultNode
have the same type. nodeDrawFunction
is flexible enough to allow them to have different types, Settings a
and Settings a10
. GHC is starting with this more general assumption, and then can't pick a specific type for a10
, since it's not constrained by anything in the function.
One option is to define nodeDrawFunction
with a less general type.
Another option is to add a type signature on def
to guide GHC. I think this will work if you add -XScopedTypeVariables
:
(def :: Settings a) & nodeDrawFunction .~ drawDefaultNode
Without ScopedTypeVariables the two type variables a
are interpreted as different, and given different unique names before type checking. If you had multiple fields in Settings
that involve a
, makeLenses
would derive lenses that cannot change a
, since no single-field lens could do so.
Upvotes: 2