    {-# LANGUAGE GADTs #-}
    ---------------------------------------------------------------------------------
    -- |
    -- Copyright   :  (C) 2012-2015 Edward Kmett
    -- License     :  BSD-style (see the file LICENSE)
    --
    -- Maintainer  :  Edward Kmett <ekmett@gmail.com>
    -- Stability   :  experimental
    -- Portability :  non-portable
    --
    -- Utility for working with Plücker coordinates for lines in 3d homogeneous space.
    ----------------------------------------------------------------------------------
    module Linear.Plucker.Coincides
      ( Coincides(..)
      ) where

    import Linear.Epsilon
    import Linear.Plucker

    -- | When lines are represented as Plücker coordinates, we have the
    -- ability to check for both directed and undirected
    -- equality. Undirected equality between 'Line's (or a 'Line' and a
    -- 'Ray') checks that the two lines coincide in 3D space. Directed
    -- equality, between two 'Ray's, checks that two lines coincide in 3D,
    -- and have the same direction. To accomodate these two notions of
    -- equality, we use an 'Eq' instance on the 'Coincides' data type.
    --
    -- For example, to check the /directed/ equality between two lines,
    -- @p1@ and @p2@, we write, @Ray p1 == Ray p2@.
    data Coincides a where
      Line :: (Epsilon a, Fractional a) => Plucker a -> Coincides a
      Ray  :: (Epsilon a, Fractional a, Ord a) => Plucker a -> Coincides a

    instance Eq (Coincides a) where
      Line Plucker a
    a == :: Coincides a -> Coincides a -> Bool
    == Line Plucker a
    b  = Plucker a -> Plucker a -> Bool
    forall a.
    (Epsilon a, Fractional a) =>
    Plucker a -> Plucker a -> Bool
    coincides Plucker a
    a Plucker a
    b
      Line Plucker a
    a == Ray Plucker a
    b   = Plucker a -> Plucker a -> Bool
    forall a.
    (Epsilon a, Fractional a) =>
    Plucker a -> Plucker a -> Bool
    coincides Plucker a
    a Plucker a
    b
      Ray Plucker a
    a  == Line Plucker a
    b  = Plucker a -> Plucker a -> Bool
    forall a.
    (Epsilon a, Fractional a) =>
    Plucker a -> Plucker a -> Bool
    coincides Plucker a
    a Plucker a
    b
      Ray Plucker a
    a  == Ray Plucker a
    b   = Plucker a -> Plucker a -> Bool
    forall a.
    (Epsilon a, Fractional a, Ord a) =>
    Plucker a -> Plucker a -> Bool
    coincides' Plucker a
    a Plucker a
    b