# LANGUAGE FlexibleInstances #
{-# LANGUAGE GADTs #-}
# LANGUAGE KindSignatures #
# LANGUAGE MultiParamTypeClasses #

{- Our -} module {- du jour is strangely-abbreviated and weirdly-capitalised:
the -} MultiParamTypeClasses {- extension opens a lot of doors for us that
we'll explore in this chapter /and/ future chapters - Let's see -} where {- we
end up! -}

import Data.Kind (Type)


   By now in your  quest , you 'll have seen many type classes . Already , 
   the ` README ` of this project has mentioned two such classes : ` Monoid ` and 
   ` Monad ` . Add these to ` Eq ` , ` Ord ` , ` Show ` , ` Functor ` ... well , we 're using a 
   lot of typeclasses ! 

   The common thread between these is that the class defines a characteristic of 
   a * * single * * type . '  ' tells us that   has a notion of equivalence . 
   ' Show ' tells us that   has a string representation . 

   Let 's think about the rough idea behind the ' Show ' class : 

  By now in your Haskell quest, you'll have seen many type classes. Already,
  the `README` of this project has mentioned two such classes: `Monoid` and
  `Monad`. Add these to `Eq`, `Ord`, `Show`, `Functor`... well, we're using a
  lot of typeclasses!

  The common thread between these is that the class defines a characteristic of
  a **single** type. 'Eq' tells us that /a type/ has a notion of equivalence.
  'Show' tells us that /a type/ has a string representation. 

  Let's think about the rough idea behind the 'Show' class:
-}

class SimpleShow (x :: Type) where
  simpleShow :: x -> String

{-
  Our class represents a type that can be transformed into a string. What if we
  want to generalise the "target" type, though? What if we want to define a
  class that characterises this relationship? Enter @MultiParamTypeClasses@.
-}

class Transform (source :: Type) (target :: Type) where
  transform :: source -> target


   We 've said here that the ' Transform ' class defines a relationship between two 
   types for which we can implement the ' transform ' function . This function has 
   a type that is hopefully not too surprising :   t = > s - > t@. Now , 
   how do we write instances ? 

  We've said here that the 'Transform' class defines a relationship between two
  types for which we can implement the 'transform' function. This function has
  a type that is hopefully not too surprising: @Transform s t => s -> t@. Now,
  how do we write instances?
-}

instance Transform Bool Int where
  transform x = if x then 1 else 0

{-
  Perfect! We write it just as we would a normal instance, except there are
  more types in the instance head. We can even use type parameters in our
  instance heads (note that using 'String' here means we need
  'FlexibleInstances' - the same rules apply, regardless of how many parameters
  you have):
-}

instance Show x => Transform x String where
  transform = show


   The @MultiParamTypeClasses@ extension also allows us to have /nullary/ 
   ( 0 - argument ) classes , though we wo n't give them much time as they 're 
   relatively straightforward . PureScript has a type class called 
   [ Partial]( / purescript / documentation / blob / master / guides / The - Partial - type - class.md ) 
   to keep track of partial functions , which gives a good intuition of the ways 
   in which these can be useful . 

  The @MultiParamTypeClasses@ extension also allows us to have /nullary/
  (0-argument) classes, though we won't give them much time as they're
  relatively straightforward. PureScript has a type class called
  [Partial](-Partial-type-class.md)
  to keep track of partial functions, which gives a good intuition of the ways
  in which these can be useful.
-}

{-
  Let's talk briefly about what happens when we have conflicting definitions.
  This isn't specific to @MultiParamTypeClasses@, and all the following rules
  apply to single-parameter type classes as well, though we're certainly more
  likely to run into these use cases in multi-parameter situations. Let's
  imagine, for example, that we want a special string representation of the
  unit type, '()'.
-}

instance Transform () String where
  transform _ = "UNIT"

{-
  All good, but we get some ugly errors when we try to use it:
-}

-- test :: String
-- test = transform ()


   • Overlapping instances for Transform ( ) String 
       arising from a use of ‘ transform ’ 
     Matching instances : 
       instance Show x = > Transform x String 
         -- Defined at src / MultiParamTypeClasses.hs:55:10 
       instance Transform ( ) String 
         -- Defined at src / MultiParamTypeClasses.hs:73:10 

   GHC has correctly realised that we actually have _ _ two _ _ instances that match 
   our needs . Because of this ambiguity , it gives us an error - it simply 
   refuses to guess . How , then , would we solve this ambiguity ? Luckily , GHC 
   provides some language pragmas to help here - let 's write a new instance : 

  • Overlapping instances for Transform () String
      arising from a use of ‘transform’
    Matching instances:
      instance Show x => Transform x String
        -- Defined at src/MultiParamTypeClasses.hs:55:10
      instance Transform () String
        -- Defined at src/MultiParamTypeClasses.hs:73:10

  GHC has correctly realised that we actually have __two__ instances that match
  our needs. Because of this ambiguity, it gives us an error - it simply
  refuses to guess. How, then, would we solve this ambiguity? Luckily, GHC
  provides some language pragmas to help here - let's write a new instance:
-}

instance {-# OVERLAPPING #-} Transform String String where
  transform = id

test2 :: String
test2 = transform "hello"


   @OVERLAPPING@ is how we tell GHC that , given the choice between this instance 
   and another , this is the " preferred " option , and should be picked . The 
   opposite pragma is @OVERLAPPABLE@ , which says " pick the other one " . 
   Fortunately , this is an either / or deal - when we have a choice between two 
   instances , GHC needs to find an @OVERLAPPING@ /or/ and @OVERLAPPABLE@ 
   instance to make a decision . Both are fine as long as they agree , though ! 

   There 's a third , more mystical pragma , however : @OVERLAPS@. Let 's have a look 
   at such an instance now : 

  @OVERLAPPING@ is how we tell GHC that, given the choice between this instance
  and another, this is the "preferred" option, and should be picked. The
  opposite pragma is @OVERLAPPABLE@, which says "pick the other one".
  Fortunately, this is an either/or deal - when we have a choice between two
  instances, GHC needs to find an @OVERLAPPING@ /or/ and @OVERLAPPABLE@
  instance to make a decision. Both are fine as long as they agree, though!

  There's a third, more mystical pragma, however: @OVERLAPS@. Let's have a look
  at such an instance now:
-}

data Which = A | B | C deriving Show

instance {-# OVERLAPS #-} Transform (f a) Which where
  transform _ = A

{-
  Now, let's introduce a couple of others:
-}

instance Transform a Which where
  transform _ = B

instance Transform (Maybe a) Which where
  transform _ = C

{-
  ... and let's use them!
-}

test3 :: Which
test3 = transform (Just (42 :: Int)) -- Prints C

test4 :: Which
test4 = transform [True] -- Prints A


   Interesting ... so , in the first case , we have two matching instances - the 
   @A@ instance and the @C@ instance . @Maybe a@ is deemed more " specific " than 
   @f a@ , and so @OVERLAPS@ acts like @OVERLAPPABLE@ , and we get the @C@ 
   instance ! 

   In the second case , however , our @[Bool]@ matches both the @A@ instance and 
   the @B@ instance . This time , @f a@ is more " specific " than @a@ , so @OVERLAPS@ 
   acts like @OVERLAPPING@ ! 

   @OVERLAPS@ is a strange pragma , and you wo n't see it used too much in the 
   wild . Furthermore , " specific " is a strange thing to intuit , but we can think 
   about it in GHC 's terms : if @x@ is a valid substitution of @y@ , but @y@ is n't 
   a valid substitution for @x@ , then @x@ is more " specific " . For example , 
   @Maybe Int@ would be a valid substitution for @Maybe a@ , but not vice versa , 
   so we consider @Maybe Int@ to be _ _ more specific _ _ . I hope that makes 
   sense ... 

  Interesting... so, in the first case, we have two matching instances - the
  @A@ instance and the @C@ instance. @Maybe a@ is deemed more "specific" than
  @f a@, and so @OVERLAPS@ acts like @OVERLAPPABLE@, and we get the @C@
  instance!

  In the second case, however, our @[Bool]@ matches both the @A@ instance and
  the @B@ instance. This time, @f a@ is more "specific" than @a@, so @OVERLAPS@
  acts like @OVERLAPPING@!

  @OVERLAPS@ is a strange pragma, and you won't see it used too much in the
  wild. Furthermore, "specific" is a strange thing to intuit, but we can think
  about it in GHC's terms: if @x@ is a valid substitution of @y@, but @y@ isn't
  a valid substitution for @x@, then @x@ is more "specific". For example,
  @Maybe Int@ would be a valid substitution for @Maybe a@, but not vice versa,
  so we consider @Maybe Int@ to be __more specific__. I hope that makes
  sense...
-}


   There is one last oft - misunderstood pragma to discuss : INCOHERENT . To 
   understand this , we 'll paraphrase [ a GHC user guide 
   entry](/~ghc/7.10.1 / docs / html / users_guide / type - class - extensions.html#instance - overlap ) 
   and step through GHC 's process when picking an instance . 

   1 . Find all instances that match given what we know already * ( those into 
      which we could " substitute " our type ) . 

   2 . Discard any less - specific overlappable instances ( or those not /as/ 
      specific as an overlapping instance ) . 

   3 . Ignoring any instances marked @INCOHERENT@ , if exactly one match remains , 
      we have a winner ! If all remaining instances /are/ marked @INCOHERENT@ , 
      pick one of them at random , and we have a winner ! ( Not really random , but 
      the choice is n't done according to some defined behaviour ) . 

   4 . If our winner is incoherent , we 're done ! 
  
   5 . If not , find all the instances that /could/ match if we knew more * . If all 
      these other instances are incoherent , return our winner ! Otherwise , we 've 
      failed , and we do n't know enough to decide :( 

   * Knowing enough is important here . Let 's clean the ` Transform ` slate and 
   look at this : 

  There is one last oft-misunderstood pragma to discuss: INCOHERENT. To
  understand this, we'll paraphrase [a GHC user guide
  entry](/~ghc/7.10.1/docs/html/users_guide/type-class-extensions.html#instance-overlap)
  and step through GHC's process when picking an instance.

  1. Find all instances that match given what we know already* (those into
     which we could "substitute" our type).

  2. Discard any less-specific overlappable instances (or those not /as/
     specific as an overlapping instance).

  3. Ignoring any instances marked @INCOHERENT@, if exactly one match remains,
     we have a winner! If all remaining instances /are/ marked @INCOHERENT@,
     pick one of them at random, and we have a winner! (Not really random, but
     the choice isn't done according to some defined behaviour).

  4. If our winner is incoherent, we're done!
  
  5. If not, find all the instances that /could/ match if we knew more*. If all
     these other instances are incoherent, return our winner! Otherwise, we've
     failed, and we don't know enough to decide :(

  * Knowing enough is important here. Let's clean the `Transform` slate and
  look at this:
-}

class Sneaky (source :: Type) (target :: Type) where
  familiar :: source -> target

instance Sneaky Float Float where
  familiar = id


   Now , let 's use ` familiar ` in a situation without giving GHC a way to figure 
   out the second type : 

  Now, let's use `familiar` in a situation without giving GHC a way to figure
  out the second type:
-}

-- -- UNCOMMENT ME
  huh = familiar ( 3.0 : : Float )


   As we 're starting to learn , GHC is actually pretty good at telling us what is 
   upsetting it . 

   • Ambiguous type variable ‘ target0 ’ arising from a use of ‘ familiar ’ 
     prevents the constraint ‘ ( Sneaky Float target0 ) ’ from being solved . 

   GHC is telling us that , until it knows what the _ second _ type is , it ca n't 
   figure out which instance to pick ! Why ? Well , for a start , we 've just seen 
   @instance Transform a Which@ , which might well be what we 're after ! Until GHC 
   knows more , it ca n't sensibly choose one or the other . Of course , there are a 
   few tricks to play here . 

  As we're starting to learn, GHC is actually pretty good at telling us what is
  upsetting it.

  • Ambiguous type variable ‘target0’ arising from a use of ‘familiar’
    prevents the constraint ‘(Sneaky Float target0)’ from being solved.

  GHC is telling us that, until it knows what the _second_ type is, it can't
  figure out which instance to pick! Why? Well, for a start, we've just seen
  @instance Transform a Which@, which might well be what we're after! Until GHC
  knows more, it can't sensibly choose one or the other. Of course, there are a
  few tricks to play here.
-}

instance a ~ [Double] => Sneaky Double a where
  familiar = pure

heh = familiar (3.0 :: Double)


   This time , no complaints ! Why ? Because in the instance head ( the bit on the 
   right - hand side of the @=>@ arrow ) , we 've said we have an instance for 
   @Double@ and /any/ second parameter you like . After we 've successfully chosen 
   that instance , the constraints /then/ tell us that the second type /must/ be 
   @Double@ , and we 'll get an error if it is n't . This separation between 
   " instance resolution " and " constraint solving " is one worth exploring , as 
   many of our clever tricks rely on it heavily . 

   Now , some of our types might have interesting instances for ' Sneaky ' , but 
   we 'd like to offer ' Sneaky a a ' as a " default " instance . In other words , we 
   only want to use this instance _ _ if all others fail _ _ . Sound familiar ? 

  This time, no complaints! Why? Because in the instance head (the bit on the
  right-hand side of the @=>@ arrow), we've said we have an instance for
  @Double@ and /any/ second parameter you like. After we've successfully chosen
  that instance, the constraints /then/ tell us that the second type /must/ be
  @Double@, and we'll get an error if it isn't. This separation between
  "instance resolution" and "constraint solving" is one worth exploring, as
  many of our clever tricks rely on it heavily.

  Now, some of our types might have interesting instances for 'Sneaky', but
  we'd like to offer 'Sneaky a a' as a "default" instance. In other words, we
  only want to use this instance __if all others fail__. Sound familiar?
-}

-- -- UNCOMMENT ME
-- instance {-# INCOHERENT #-} a ~ b => Sneaky a b where
--   familiar = id


   Here 's a scary - looking line of code , right ? What we 're saying here is , if you 
   ca n't find an instance to suit your needs , this " fallback " instance will 
   work . The only constraint is that your @a@ and  types must be the same 
   type . Because it 's marked as @INCOHERENT@ , we 'll totally ignore it /unless/ 
   we have no other option . Perfect ! 

   Now , this all sounds sensible , so ... why the scary name ? Friends , we have 
   some misconceptions to address : 

   1 . _ Most _ " incoherence " around type classes comes from what we call /orphan 
      instances/. These are instances defined for types that exist neither in 
      the same module as the type declaration /nor/ the class declaration . If 
      we avoid orphan instances ( by , for example , creating @newtype@s when we 
      want different behaviours instead of overlapping existing instances ) , 
      there is no incoherence with @OVERLAPPING@ , @OVERLAPS@ , or @OVERLAPPABLE@ , 
      thus they are simply safe – and extremely useful – tools for us to use . 

   2 . @INCOHERENT@ instances only become incoherent when GHC is given a choice 
      between more than one of them . If you only ever have one defined - or find 
      a clever way to avoid ever matching more than one * - then this is a very 
      scary name for a not - very - scary idea . Just ... be careful with this one , 
      OK ? If you can convince yourself that , following the steps of instance 
      resolution above , GHC 's selection will always be predictable , then this is 
      all good . /Be careful/. 

   * -deriving-bifunctor/#incoherent-instances 

  Here's a scary-looking line of code, right? What we're saying here is, if you
  can't find an instance to suit your needs, this "fallback" instance will
  work. The only constraint is that your @a@ and @b@ types must be the same
  type. Because it's marked as @INCOHERENT@, we'll totally ignore it /unless/
  we have no other option. Perfect!

  Now, this all sounds sensible, so... why the scary name? Friends, we have
  some misconceptions to address:

  1. _Most_ "incoherence" around type classes comes from what we call /orphan
     instances/. These are instances defined for types that exist neither in
     the same module as the type declaration /nor/ the class declaration. If
     we avoid orphan instances (by, for example, creating @newtype@s when we
     want different behaviours instead of overlapping existing instances),
     there is no incoherence with @OVERLAPPING@, @OVERLAPS@, or @OVERLAPPABLE@,
     thus they are simply safe – and extremely useful – tools for us to use.

  2. @INCOHERENT@ instances only become incoherent when GHC is given a choice
     between more than one of them. If you only ever have one defined - or find
     a clever way to avoid ever matching more than one* - then this is a very
     scary name for a not-very-scary idea. Just... be careful with this one,
     OK? If you can convince yourself that, following the steps of instance
     resolution above, GHC's selection will always be predictable, then this is
     all good. /Be careful/.

  * -deriving-bifunctor/#incoherent-instances
-}

# LANGUAGE GADTs #
 Our 
 du jour is strangely-abbreviated and weirdly-capitalised:
the 
 extension opens a lot of doors for us that
we'll explore in this chapter /and/ future chapters - Let's see 
 we
end up! 

  Our class represents a type that can be transformed into a string. What if we
  want to generalise the "target" type, though? What if we want to define a
  class that characterises this relationship? Enter @MultiParamTypeClasses@.


  Perfect! We write it just as we would a normal instance, except there are
  more types in the instance head. We can even use type parameters in our
  instance heads (note that using 'String' here means we need
  'FlexibleInstances' - the same rules apply, regardless of how many parameters
  you have):


  Let's talk briefly about what happens when we have conflicting definitions.
  This isn't specific to @MultiParamTypeClasses@, and all the following rules
  apply to single-parameter type classes as well, though we're certainly more
  likely to run into these use cases in multi-parameter situations. Let's
  imagine, for example, that we want a special string representation of the
  unit type, '()'.


  All good, but we get some ugly errors when we try to use it:

 test :: String
 test = transform ()
 Defined at src / MultiParamTypeClasses.hs:55:10 
 Defined at src / MultiParamTypeClasses.hs:73:10 
 Defined at src/MultiParamTypeClasses.hs:55:10
 Defined at src/MultiParamTypeClasses.hs:73:10
# OVERLAPPING #
# OVERLAPS #

  Now, let's introduce a couple of others:


  ... and let's use them!

 Prints C
 Prints A
 -- UNCOMMENT ME
 -- UNCOMMENT ME
 instance {-# INCOHERENT #-} a ~ b => Sneaky a b where
   familiar = id
# LANGUAGE FlexibleInstances #
# LANGUAGE KindSignatures #
# LANGUAGE MultiParamTypeClasses #


import Data.Kind (Type)


   By now in your  quest , you 'll have seen many type classes . Already , 
   the ` README ` of this project has mentioned two such classes : ` Monoid ` and 
   ` Monad ` . Add these to ` Eq ` , ` Ord ` , ` Show ` , ` Functor ` ... well , we 're using a 
   lot of typeclasses ! 

   The common thread between these is that the class defines a characteristic of 
   a * * single * * type . '  ' tells us that   has a notion of equivalence . 
   ' Show ' tells us that   has a string representation . 

   Let 's think about the rough idea behind the ' Show ' class : 

  By now in your Haskell quest, you'll have seen many type classes. Already,
  the `README` of this project has mentioned two such classes: `Monoid` and
  `Monad`. Add these to `Eq`, `Ord`, `Show`, `Functor`... well, we're using a
  lot of typeclasses!

  The common thread between these is that the class defines a characteristic of
  a **single** type. 'Eq' tells us that /a type/ has a notion of equivalence.
  'Show' tells us that /a type/ has a string representation. 

  Let's think about the rough idea behind the 'Show' class:
-}

class SimpleShow (x :: Type) where
  simpleShow :: x -> String


class Transform (source :: Type) (target :: Type) where
  transform :: source -> target


   We 've said here that the ' Transform ' class defines a relationship between two 
   types for which we can implement the ' transform ' function . This function has 
   a type that is hopefully not too surprising :   t = > s - > t@. Now , 
   how do we write instances ? 

  We've said here that the 'Transform' class defines a relationship between two
  types for which we can implement the 'transform' function. This function has
  a type that is hopefully not too surprising: @Transform s t => s -> t@. Now,
  how do we write instances?
-}

instance Transform Bool Int where
  transform x = if x then 1 else 0


instance Show x => Transform x String where
  transform = show


   The @MultiParamTypeClasses@ extension also allows us to have /nullary/ 
   ( 0 - argument ) classes , though we wo n't give them much time as they 're 
   relatively straightforward . PureScript has a type class called 
   [ Partial]( / purescript / documentation / blob / master / guides / The - Partial - type - class.md ) 
   to keep track of partial functions , which gives a good intuition of the ways 
   in which these can be useful . 

  The @MultiParamTypeClasses@ extension also allows us to have /nullary/
  (0-argument) classes, though we won't give them much time as they're
  relatively straightforward. PureScript has a type class called
  [Partial](-Partial-type-class.md)
  to keep track of partial functions, which gives a good intuition of the ways
  in which these can be useful.
-}


instance Transform () String where
  transform _ = "UNIT"




   • Overlapping instances for Transform ( ) String 
       arising from a use of ‘ transform ’ 
     Matching instances : 
       instance Show x = > Transform x String 
       instance Transform ( ) String 

   GHC has correctly realised that we actually have _ _ two _ _ instances that match 
   our needs . Because of this ambiguity , it gives us an error - it simply 
   refuses to guess . How , then , would we solve this ambiguity ? Luckily , GHC 
   provides some language pragmas to help here - let 's write a new instance : 

  • Overlapping instances for Transform () String
      arising from a use of ‘transform’
    Matching instances:
      instance Show x => Transform x String
      instance Transform () String

  GHC has correctly realised that we actually have __two__ instances that match
  our needs. Because of this ambiguity, it gives us an error - it simply
  refuses to guess. How, then, would we solve this ambiguity? Luckily, GHC
  provides some language pragmas to help here - let's write a new instance:
-}

  transform = id

test2 :: String
test2 = transform "hello"


   @OVERLAPPING@ is how we tell GHC that , given the choice between this instance 
   and another , this is the " preferred " option , and should be picked . The 
   opposite pragma is @OVERLAPPABLE@ , which says " pick the other one " . 
   Fortunately , this is an either / or deal - when we have a choice between two 
   instances , GHC needs to find an @OVERLAPPING@ /or/ and @OVERLAPPABLE@ 
   instance to make a decision . Both are fine as long as they agree , though ! 

   There 's a third , more mystical pragma , however : @OVERLAPS@. Let 's have a look 
   at such an instance now : 

  @OVERLAPPING@ is how we tell GHC that, given the choice between this instance
  and another, this is the "preferred" option, and should be picked. The
  opposite pragma is @OVERLAPPABLE@, which says "pick the other one".
  Fortunately, this is an either/or deal - when we have a choice between two
  instances, GHC needs to find an @OVERLAPPING@ /or/ and @OVERLAPPABLE@
  instance to make a decision. Both are fine as long as they agree, though!

  There's a third, more mystical pragma, however: @OVERLAPS@. Let's have a look
  at such an instance now:
-}

data Which = A | B | C deriving Show

  transform _ = A


instance Transform a Which where
  transform _ = B

instance Transform (Maybe a) Which where
  transform _ = C


test3 :: Which

test4 :: Which


   Interesting ... so , in the first case , we have two matching instances - the 
   @A@ instance and the @C@ instance . @Maybe a@ is deemed more " specific " than 
   @f a@ , and so @OVERLAPS@ acts like @OVERLAPPABLE@ , and we get the @C@ 
   instance ! 

   In the second case , however , our @[Bool]@ matches both the @A@ instance and 
   the @B@ instance . This time , @f a@ is more " specific " than @a@ , so @OVERLAPS@ 
   acts like @OVERLAPPING@ ! 

   @OVERLAPS@ is a strange pragma , and you wo n't see it used too much in the 
   wild . Furthermore , " specific " is a strange thing to intuit , but we can think 
   about it in GHC 's terms : if @x@ is a valid substitution of @y@ , but @y@ is n't 
   a valid substitution for @x@ , then @x@ is more " specific " . For example , 
   @Maybe Int@ would be a valid substitution for @Maybe a@ , but not vice versa , 
   so we consider @Maybe Int@ to be _ _ more specific _ _ . I hope that makes 
   sense ... 

  Interesting... so, in the first case, we have two matching instances - the
  @A@ instance and the @C@ instance. @Maybe a@ is deemed more "specific" than
  @f a@, and so @OVERLAPS@ acts like @OVERLAPPABLE@, and we get the @C@
  instance!

  In the second case, however, our @[Bool]@ matches both the @A@ instance and
  the @B@ instance. This time, @f a@ is more "specific" than @a@, so @OVERLAPS@
  acts like @OVERLAPPING@!

  @OVERLAPS@ is a strange pragma, and you won't see it used too much in the
  wild. Furthermore, "specific" is a strange thing to intuit, but we can think
  about it in GHC's terms: if @x@ is a valid substitution of @y@, but @y@ isn't
  a valid substitution for @x@, then @x@ is more "specific". For example,
  @Maybe Int@ would be a valid substitution for @Maybe a@, but not vice versa,
  so we consider @Maybe Int@ to be __more specific__. I hope that makes
  sense...
-}


   There is one last oft - misunderstood pragma to discuss : INCOHERENT . To 
   understand this , we 'll paraphrase [ a GHC user guide 
   entry](/~ghc/7.10.1 / docs / html / users_guide / type - class - extensions.html#instance - overlap ) 
   and step through GHC 's process when picking an instance . 

   1 . Find all instances that match given what we know already * ( those into 
      which we could " substitute " our type ) . 

   2 . Discard any less - specific overlappable instances ( or those not /as/ 
      specific as an overlapping instance ) . 

   3 . Ignoring any instances marked @INCOHERENT@ , if exactly one match remains , 
      we have a winner ! If all remaining instances /are/ marked @INCOHERENT@ , 
      pick one of them at random , and we have a winner ! ( Not really random , but 
      the choice is n't done according to some defined behaviour ) . 

   4 . If our winner is incoherent , we 're done ! 
  
   5 . If not , find all the instances that /could/ match if we knew more * . If all 
      these other instances are incoherent , return our winner ! Otherwise , we 've 
      failed , and we do n't know enough to decide :( 

   * Knowing enough is important here . Let 's clean the ` Transform ` slate and 
   look at this : 

  There is one last oft-misunderstood pragma to discuss: INCOHERENT. To
  understand this, we'll paraphrase [a GHC user guide
  entry](/~ghc/7.10.1/docs/html/users_guide/type-class-extensions.html#instance-overlap)
  and step through GHC's process when picking an instance.

  1. Find all instances that match given what we know already* (those into
     which we could "substitute" our type).

  2. Discard any less-specific overlappable instances (or those not /as/
     specific as an overlapping instance).

  3. Ignoring any instances marked @INCOHERENT@, if exactly one match remains,
     we have a winner! If all remaining instances /are/ marked @INCOHERENT@,
     pick one of them at random, and we have a winner! (Not really random, but
     the choice isn't done according to some defined behaviour).

  4. If our winner is incoherent, we're done!
  
  5. If not, find all the instances that /could/ match if we knew more*. If all
     these other instances are incoherent, return our winner! Otherwise, we've
     failed, and we don't know enough to decide :(

  * Knowing enough is important here. Let's clean the `Transform` slate and
  look at this:
-}

class Sneaky (source :: Type) (target :: Type) where
  familiar :: source -> target

instance Sneaky Float Float where
  familiar = id


   Now , let 's use ` familiar ` in a situation without giving GHC a way to figure 
   out the second type : 

  Now, let's use `familiar` in a situation without giving GHC a way to figure
  out the second type:
-}

  huh = familiar ( 3.0 : : Float )


   As we 're starting to learn , GHC is actually pretty good at telling us what is 
   upsetting it . 

   • Ambiguous type variable ‘ target0 ’ arising from a use of ‘ familiar ’ 
     prevents the constraint ‘ ( Sneaky Float target0 ) ’ from being solved . 

   GHC is telling us that , until it knows what the _ second _ type is , it ca n't 
   figure out which instance to pick ! Why ? Well , for a start , we 've just seen 
   @instance Transform a Which@ , which might well be what we 're after ! Until GHC 
   knows more , it ca n't sensibly choose one or the other . Of course , there are a 
   few tricks to play here . 

  As we're starting to learn, GHC is actually pretty good at telling us what is
  upsetting it.

  • Ambiguous type variable ‘target0’ arising from a use of ‘familiar’
    prevents the constraint ‘(Sneaky Float target0)’ from being solved.

  GHC is telling us that, until it knows what the _second_ type is, it can't
  figure out which instance to pick! Why? Well, for a start, we've just seen
  @instance Transform a Which@, which might well be what we're after! Until GHC
  knows more, it can't sensibly choose one or the other. Of course, there are a
  few tricks to play here.
-}

instance a ~ [Double] => Sneaky Double a where
  familiar = pure

heh = familiar (3.0 :: Double)


   This time , no complaints ! Why ? Because in the instance head ( the bit on the 
   right - hand side of the @=>@ arrow ) , we 've said we have an instance for 
   @Double@ and /any/ second parameter you like . After we 've successfully chosen 
   that instance , the constraints /then/ tell us that the second type /must/ be 
   @Double@ , and we 'll get an error if it is n't . This separation between 
   " instance resolution " and " constraint solving " is one worth exploring , as 
   many of our clever tricks rely on it heavily . 

   Now , some of our types might have interesting instances for ' Sneaky ' , but 
   we 'd like to offer ' Sneaky a a ' as a " default " instance . In other words , we 
   only want to use this instance _ _ if all others fail _ _ . Sound familiar ? 

  This time, no complaints! Why? Because in the instance head (the bit on the
  right-hand side of the @=>@ arrow), we've said we have an instance for
  @Double@ and /any/ second parameter you like. After we've successfully chosen
  that instance, the constraints /then/ tell us that the second type /must/ be
  @Double@, and we'll get an error if it isn't. This separation between
  "instance resolution" and "constraint solving" is one worth exploring, as
  many of our clever tricks rely on it heavily.

  Now, some of our types might have interesting instances for 'Sneaky', but
  we'd like to offer 'Sneaky a a' as a "default" instance. In other words, we
  only want to use this instance __if all others fail__. Sound familiar?
-}



   Here 's a scary - looking line of code , right ? What we 're saying here is , if you 
   ca n't find an instance to suit your needs , this " fallback " instance will 
   work . The only constraint is that your @a@ and  types must be the same 
   type . Because it 's marked as @INCOHERENT@ , we 'll totally ignore it /unless/ 
   we have no other option . Perfect ! 

   Now , this all sounds sensible , so ... why the scary name ? Friends , we have 
   some misconceptions to address : 

   1 . _ Most _ " incoherence " around type classes comes from what we call /orphan 
      instances/. These are instances defined for types that exist neither in 
      the same module as the type declaration /nor/ the class declaration . If 
      we avoid orphan instances ( by , for example , creating @newtype@s when we 
      want different behaviours instead of overlapping existing instances ) , 
      there is no incoherence with @OVERLAPPING@ , @OVERLAPS@ , or @OVERLAPPABLE@ , 
      thus they are simply safe – and extremely useful – tools for us to use . 

   2 . @INCOHERENT@ instances only become incoherent when GHC is given a choice 
      between more than one of them . If you only ever have one defined - or find 
      a clever way to avoid ever matching more than one * - then this is a very 
      scary name for a not - very - scary idea . Just ... be careful with this one , 
      OK ? If you can convince yourself that , following the steps of instance 
      resolution above , GHC 's selection will always be predictable , then this is 
      all good . /Be careful/. 

   * -deriving-bifunctor/#incoherent-instances 

  Here's a scary-looking line of code, right? What we're saying here is, if you
  can't find an instance to suit your needs, this "fallback" instance will
  work. The only constraint is that your @a@ and @b@ types must be the same
  type. Because it's marked as @INCOHERENT@, we'll totally ignore it /unless/
  we have no other option. Perfect!

  Now, this all sounds sensible, so... why the scary name? Friends, we have
  some misconceptions to address:

  1. _Most_ "incoherence" around type classes comes from what we call /orphan
     instances/. These are instances defined for types that exist neither in
     the same module as the type declaration /nor/ the class declaration. If
     we avoid orphan instances (by, for example, creating @newtype@s when we
     want different behaviours instead of overlapping existing instances),
     there is no incoherence with @OVERLAPPING@, @OVERLAPS@, or @OVERLAPPABLE@,
     thus they are simply safe – and extremely useful – tools for us to use.

  2. @INCOHERENT@ instances only become incoherent when GHC is given a choice
     between more than one of them. If you only ever have one defined - or find
     a clever way to avoid ever matching more than one* - then this is a very
     scary name for a not-very-scary idea. Just... be careful with this one,
     OK? If you can convince yourself that, following the steps of instance
     resolution above, GHC's selection will always be predictable, then this is
     all good. /Be careful/.

  * -deriving-bifunctor/#incoherent-instances
-}
