title: Type constraints become huge and unreadable for simple code
body: <p>Mind the following code:</p>
  
  <pre><code>-- A n-dimensional axis aligned bounding box.
  data AABB v a = AABB {
      aabbMin :: !(v a), 
      aabbMax :: !(v a)
      } deriving (Show)
  
  -- `v` is a container, representing the number of dimensions. Ex:
  -- type Box2DFloat = AABB V2 Float
  -- type Box4DFloat = AABB V4 Float 
  
  -- A n-dimensional ray.
  data Ray v a = Ray {
      rayPos :: !(v a),
      rayDir :: !(v a)
      } deriving (Show)
  
  -- Traces a n-d ray through a n-d box, returns 
  -- the intersection indexes (tmin, tmax).
  intersectAABB 
      :: (Foldable f, 
          Metric f, 
          Ord a, 
          Num (f a), 
          Fractional (f a), 
          Floating a) 
      =&gt; Ray f a 
      -&gt; AABB f a 
      -&gt; [a]
  intersectAABB (Ray rayPos rayDir) (AABB aabbMin aabbMax) 
      = [tmin, tmax] where
          t1   = (aabbMin - rayPos) / rayDir
          t2   = (aabbMax - rayPos) / rayDir
          tmin = foldr1 max $ liftI2 min t1 t2
          tmax = foldr1 min $ liftI2 max t1 t2
  </code></pre>
  
  <p>That is an usual Ray→AABB intersection function, and it is pretty simple and clean, except for <strong>the type signature, which is almost bigger than the function itself</strong>! Someone suggested I could use kind constraints that "encapsule my needs" to make it less verbose, but I can't find a kind constraint that "encapsules my needs" properly. "My needs", on this case, are basically "the type acts like a number should". So, on my mind, the following would make sense:</p>
  
  <pre><code>class Real a where
      ... anything I want a real number to do ...
  
  instance Real Float where
      ...
  
  instance (Real a) =&gt; Real (V2 a) where
      ...
  
  instance (Real a) =&gt; Real (V3 a) where
      ...
  
  type AABB a = V2 a
  type Ray a  = V2 a
  
  type Box2DFloat = AABB (V2 Float)
  type Box4DFloat = AABB (V4 Float)
  type Ray2D a = Ray (V2 a)
  type Ray3DRatio = Ray (V3 Ratio)
  ... etc ...
  </code></pre>
  
  <p>That way, my signatures would become, simply:</p>
  
  <pre><code>intersectAABB :: (Real r, Real s) =&gt; Ray r -&gt; AABB r -&gt; [s]
  </code></pre>
  
  <p>Which looks much better. But, if nobody using Haskell has bothered to define such class, there should be a reason. What is the reason there is no "Real" class, and, if defining such a class would be a bad idea, what is the proper solution to my issue?</p>