    {-# OPTIONS_GHC -fno-warn-orphans #-}
    {-# LANGUAGE FlexibleInstances #-}
    {-# LANGUAGE TypeOperators #-}

    -- |
    -- Module      : Data.Functor.ProductIsomorphic.GenericInstances
    -- Copyright   : 2017 Kei Hibino
    -- License     : BSD3
    --
    -- Maintainer  : ex8k.hibino@gmail.com
    -- Stability   : experimental
    -- Portability : unknown
    --
    -- This module defines instances for constructors used in generic-programming.
    module Data.Functor.ProductIsomorphic.GenericInstances () where

    import GHC.Generics
      (U1 (U1), K1 (K1), M1 (M1), (:*:) ((:*:)), )
    -- import GHC.Generics (Generic, Rep, from, to, )

    import Data.Functor.ProductIsomorphic.Unsafe (ProductConstructor (..))

    instance ProductConstructor (U1 p) where
      productConstructor :: U1 p
    productConstructor = U1 p
    forall k (p :: k). U1 p
    U1
      {-# INLINEABLE productConstructor #-}

    instance ProductConstructor (c -> K1 i c p) where
      productConstructor :: c -> K1 i c p
    productConstructor = c -> K1 i c p
    forall k i c (p :: k). c -> K1 i c p
    K1
      {-# INLINEABLE productConstructor #-}

    instance ProductConstructor (f p -> M1 i c f p) where
      productConstructor :: f p -> M1 i c f p
    productConstructor = f p -> M1 i c f p
    forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
    M1
      {-# INLINEABLE productConstructor #-}

    instance ProductConstructor (f x -> g x -> (f :*: g) x) where
      productConstructor :: f x -> g x -> (:*:) f g x
    productConstructor = f x -> g x -> (:*:) f g x
    forall k (f :: k -> *) (g :: k -> *) (p :: k).
    f p -> g p -> (:*:) f g p
    (:*:)
      {-# INLINEABLE productConstructor #-}

    {- -- why compile error?
    instance Generic a => ProductConstructor (a -> Rep a x) where
      productConstructor = from

    instance Generic a => ProductConstructor (Rep a x -> a) where
      productConstructor = to
     -}