Skip to content

Type error being deferred to other values

Summary

The following code doesn't type check because of the last line <> radius, which has type Double while the rest of the values have type Diagram B.

{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE TypeFamilies              #-}
module Test where

import Diagrams.Prelude
import Diagrams.Backend.SVG.CmdLine

someFunc :: Double -> Diagram B
someFunc radius = result
    where
        commonSubExpr = circle radius

        unrelatedValue
            = commonSubExpr
           <> (circle 5 :: Diagram B)
        
        result
            = commonSubExpr
            <> (circle 1 :: Diagram B)
            <> radius

However, GHC prints out type errors on almost every value but the radius:

...\Test.hs:9:19: error:
    * Couldn't match type `Double' with `QDiagram B (V B) (N B) Any'
      Expected type: Diagram B
        Actual type: Double
    * In the expression: result
      In an equation for `someFunc':
          someFunc radius
            = result
            where
                commonSubExpr = circle radius
                unrelatedValue = commonSubExpr <> (circle 5 :: Diagram B)
                result = commonSubExpr <> (circle 1 :: Diagram B) <> radius
  |
9 | someFunc radius = result
  |                   ^^^^^^

...\Test.hs:15:16: error:
    * Couldn't match type `QDiagram B (V B) (N B) Any' with `Double'
      Expected type: Double
        Actual type: Diagram B
    * In the second argument of `(<>)', namely
        `(circle 5 :: Diagram B)'
      In the expression: commonSubExpr <> (circle 5 :: Diagram B)
      In an equation for `unrelatedValue':
          unrelatedValue = commonSubExpr <> (circle 5 :: Diagram B)
   |
15 |            <> (circle 5 :: Diagram B)
   |                ^^^^^^^^^^^^^^^^^^^^^

...\Test.hs:19:17: error:
    * Couldn't match type `QDiagram B (V B) (N B) Any' with `Double'
      Expected type: Double
        Actual type: Diagram B
    * In the first argument of `(<>)', namely `(circle 1 :: Diagram B)'
      In the second argument of `(<>)', namely
        `(circle 1 :: Diagram B) <> radius'
      In the expression:
        commonSubExpr <> (circle 1 :: Diagram B) <> radius
   |
19 |             <> (circle 1 :: Diagram B)
   |                 ^^^^^^^^^^^^^^^^^^^^^

where QDiagram B (V B) (N B) Any is what Diagram B resolves to.

There is a lot of odd with this. For one, GHC seems convinced that the type of result is Double even though Double doesn't even have a Semigroup instance. Secondly, the type error seems to spread through commonSubExpr into unrelatedValue. Additionally circle x returns a value from a typeclass called TrailLike, but the typeclass doesn't have an instance for Double, so it's a bit odd that GHC doesn't have a problem with the type of commonSubExpr.

Also, if you replace the definition of commonSubExpr with commonSubExpr = circle (1.2 :: Double), GHC will stop reporting the second type error even though the types of all expresions should be the same.

Steps to reproduce

Compile the above code along with the diagrams-lib, diagrams and diagrams-svg libraries.

Expected behavior

I expected GHC to give an error about the right and left arguments of the last <> being different, thus pointing directly to the source of the type error.

Environment

  • GHC version used: 8.6.5
  • Diagrams version used: 1.4 (for all 3 libraries)

Optional:

  • Operating System: Windows 10
  • System Architecture: x86-64
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information