Remove the type-checking knot.
[ghc.git] / testsuite / tests / polykinds / T7332.hs
1 {-# LANGUAGE NoMonomorphismRestriction #-}
2 {-# LANGUAGE MultiParamTypeClasses #-}
3 {-# LANGUAGE FlexibleInstances, FlexibleContexts #-}
4 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
5 {-# LANGUAGE TypeFamilies #-}
6 {-# LANGUAGE OverloadedStrings #-}
7
8 module T7332 where
9
10 import GHC.Exts( IsString(..) )
11 import Data.Monoid
12 import Data.Semigroup
13
14 newtype DC d = DC d
15 deriving (Show, Semigroup, Monoid)
16
17 instance IsString (DC String) where
18 fromString = DC
19
20
21 class Monoid acc => Build acc r where
22 type BuildR r :: * -- Result type
23 build :: (acc -> BuildR r) -> acc -> r
24
25 instance Monoid dc => Build dc (DC dx) where
26 type BuildR (DC dx) = DC dx
27 build tr acc = tr acc
28
29 instance (Build dc r, a ~ dc) => Build dc (a->r) where
30 type BuildR (a->r) = BuildR r
31 build tr acc s = build tr (acc `mappend` s)
32
33
34 -- The type is inferred
35 -- tspan :: (Monoid d, Build (DC d) r, BuildR r ~ DC d) => r
36 tspan :: (Build (DC d) r, BuildR r ~ DC d) => r
37 tspan = build (id :: DC d -> DC d) mempty
38
39 {- Solving 'tspan'
40
41 Given: Build (DC d) r, BuildR r ~ DC d
42 (by sc) Monoid (DC d)
43
44 Wanted:
45 Build acc0 r0
46 Monid acc0
47 acc0 ~ DC d0
48 DC d0 ~ BuildR r0
49 r ~ r0
50 ==>
51 Build (DC d0) r
52 Monoid (DC d0) --> Monoid d0
53 DC d0 ~ BuildR r
54
55 From Given: BuildR r = DC d, hence
56 DC d0 ~ DC d
57 hence
58 d0 ~ d
59
60 ===>
61 Build (DC d) r
62 Monoid (DC d)
63
64 Now things are delicate. Either the instance Monoid (DC d) will fire or,
65 if we are lucky, we might spot that (Monoid (DC d)) is a superclass of
66 a given. But now (Decl 15) we add superclasses lazily, so that is less
67 likely to happen, and was always fragile. So include (Monoid d) in the
68 signature, as was the case in the original ticket.
69 -}
70
71
72 foo = tspan "aa"
73
74 foo1 = tspan (tspan "aa")
75
76 bar = tspan "aa" :: DC String