<div dir="ltr"><div dir="ltr"><div>Hi Olaf!</div><div><br></div><div>Sorry for a bit of delay, I finally managed to digest your inputs.<br></div></div><br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Your existential type AnyNum is the union of all number types, but even<br>
set-theoretically there is no way of extending individual operations on<br>
many sets to a single operation on the union of all sets, even when the<br>
operations commute with subset inclusion. That ony works if the union<br>
is directed (see attached), that is, if for every two sets A and B<br>
there is a third set C in the union of which both other sets are a<br>
subset. <br></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
So in order to implement<br>
    AnyNum (5 :: Rational) + AnyNum (NaN :: Double)<br>
you first have to find a single other Num type that Rational and Double<br>
can be cast into, then perform the (+) there. <br></blockquote><div><br></div><div>Thank you for the example! I managed to play around with it, and added a bit more general examples:<br></div><div><br></div><div>```</div><div>instance Castable Integer Double where<br>  cast1 = fromInteger<br>instance Castable Rational Double where<br>  cast1 = fromRational<br>instance Castable Double Double where<br>  cast1 = id<br>instance (Castable a Double, Castable b Double) => Directed Num a b Double where<br>    castUnion _ (a, b) = (cast1 a, cast1 b)<br>genericPlus ::<br>  forall a b c.<br>  (Num a, Num b, Num c, Directed Num a b c) =><br>  a -> b -> c<br>genericPlus = castOp (Proxy :: Proxy Num) (+)<br><br>main = do<br>  print $ show $ genericPlus (2 :: Integer) (5 :: Integer)<br>  print $ show $ genericPlus (1/3 :: Rational) (5 :: Integer)<br>  print $ show $ genericPlus (1/3 :: Rational) (2/3 :: Rational)<br>  print $ show $ genericPlus (4 :: Integer) (2/3 :: Rational)<br></div><div>```</div><br><div>That's interesting, it also makes me think how the C language style of "implicit casting" is working under the hood.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
What the libraries like generics-sop, attenuation and to some extent<br>
the Prelude do is to construct a hierarchy either via multi-parameter<br>
type classes<br>
     A `IsSubtypeOf` B<br>
or constrained classes like<br>
     Num a => Fractional a<br>
That may culminate in a most inclusive type or type class, providing<br>
all the operations of its ancestors. Notice the reversal of<br>
inclusions: <br>
<br>
Integer `IsSubtypeOf` Rational<br>
fromInteger :: Integer -> Rational <br>
instance Num Integer<br>
instance Fractional Rational<br>
Rational `IsSubclassOf` Num<br>
<br>
Instead of the union of all types under consideration, maybe the<br>
intersection is useful to you. Attached is a module that implements the<br>
initial object of a class (which I think in the case of Num is<br>
isomorphic to Integer), that is a type that can do everything every<br>
other Num type can do, but nothing more. AnyNum is the terminal object<br>
of Num.<br>
<br>
-- The initial object in the Num class<br>
newtype FreeNum = FreeNum {<br>
    runNum :: forall r.<br>
        (Integer -> r) -> -- fromInteger<br>
        (r -> r -> r) ->  -- (+)<br>
        (r -> r -> r) ->  -- (*)<br>
        (r -> r) ->       -- negate<br>
        (r -> r) ->       -- abs<br>
        (r -> r) ->       -- signum<br>
        r     <br>
    }<br>
<br>
On this, we can implement numeric operations without casting. <br></blockquote><div><br></div><div>That's the next level... I don't think I can manage to figure out how to define "operations in NumSig num" or even a `freeDouble` today...</div><div><br></div><div>Although it already deviates from my original inquiry, which was about run-time polymorhpism and have some sort of OO-style INum class in Haskell. As later I figured out, a "+=" operator would make
 more sense for "objects", and type checkings could be run-time using 
Typeable. But I learned something already, fun exercise so far though!</div><div><br></div><div>Best regards,</div><div>Miao<br></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Olaf<br>
</blockquote></div></div>