content: {-# LANGUAGE NoMonomorphismRestriction #-}
  {-# LANGUAGE MultiParamTypeClasses #-}
  {-# LANGUAGE FlexibleInstances, FlexibleContexts #-}
  {-# LANGUAGE GeneralizedNewtypeDeriving #-}
  {-# LANGUAGE TypeFamilies #-}
  {-# LANGUAGE OverloadedStrings #-}
  
  module T7332 where
  
  import GHC.Exts( IsString(..) )
  import Data.Kind (Type)
  import Data.Monoid
  import Data.Semigroup
  
  newtype DC d = DC d
      deriving (Show, Semigroup, Monoid)
  
  instance IsString (DC String) where
      fromString = DC
  
  
  class Monoid acc => Build acc r where
      type BuildR r :: Type       -- Result type
      build :: (acc -> BuildR r) -> acc -> r
  
  instance Monoid dc => Build dc (DC dx) where
      type BuildR (DC dx) = DC dx
      build tr acc = tr acc
  
  instance (Build dc r, a ~ dc) => Build dc (a->r) where
      type BuildR (a->r) = BuildR r
      build tr acc s = build tr (acc `mappend` s)
  
  
  -- The type is inferred
  -- tspan :: (Monoid d, Build (DC d) r, BuildR r ~ DC d) => r
  tspan :: (Build (DC d) r, BuildR r ~ DC d) => r
  tspan = build (id :: DC d -> DC d) mempty
  
  {- Solving 'tspan'
  
  Given:    Build (DC d) r, BuildR r ~ DC d
   (by sc)  Monoid (DC d)
  
     Wanted:
         Build acc0 r0
         Monid acc0
         acc0 ~ DC d0
         DC d0 ~ BuildR r0
         r ~ r0
  ==>
         Build (DC d0) r
         Monoid (DC d0)  -->  Monoid d0
         DC d0 ~ BuildR r
  
  From Given: BuildR r = DC d, hence
         DC d0 ~ DC d
  hence
         d0 ~ d
  
  ===>
         Build (DC d) r
         Monoid (DC d)
  
  Now things are delicate.  Either the instance Monoid (DC d) will fire or,
  if we are lucky, we might spot that (Monoid (DC d)) is a superclass of
  a given.  But now (Decl 15) we add superclasses lazily, so that is less
  likely to happen, and was always fragile.  So include (Monoid d) in the
  signature, as was the case in the original ticket.
  -}
  
  
  foo = tspan "aa"
  
  foo1 = tspan (tspan "aa")
  
  bar = tspan "aa" :: DC String
  