Universeller Transformator in Haskell

Logischerweise ist es möglich, universelle Transformationsfunktionen zu definieren, die von jedem Typ in jeden Typ transformiert werden können.

Der mögliche Weg ist:

{-#LANGUAGE MultiParamTypeClasses #-}
{-#LANGUAGE FlexibleInstances #-}

class FromTo a b where
    fromTo:: a->b

instance FromTo a a where fromTo = id

instance FromTo Int     Double where fromTo = fromIntegral
instance FromTo Int     Float  where fromTo = fromIntegral
instance FromTo Integer Double where fromTo = fromIntegral
instance FromTo Integer Float  where fromTo = fromIntegral

instance FromTo Double Int     where fromTo = round 
instance FromTo Double Integer where fromTo = round 
instance FromTo Float  Int     where fromTo = round 
instance FromTo Float  Integer where fromTo = round
-- e.t.c.

Nun, es funktioniert, es ist erweiterbar. Aber es ist sehr sperrig, weil ich jeden Fall auflisten muss, den ich verwenden möchte.

Gibt es dafür gute Lösungen?

Die ordentliche Lösung könnte so aussehen, wenn sie richtig wäre(aber es ist nicht):

{-#LANGUAGE MultiParamTypeClasses #-}
{-#LANGUAGE FlexibleInstances #-}
{-#LANGUAGE InstanceSigs #-}

class FromTo a b where
    fromTo:: a->b

instance (Integral a, Num b) => FromTo a b where
    fromTo::a->b
    fromTo x = (fromIntegral x)

{---Commented, because addition breaks program.-------------------------------
instance (RealFrac a, Integral b) => FromTo a b where
    fromTo::a->b
    fromTo x = (round x)
-}

Vielleicht wäre es möglich, wenn es eine Erweiterung für Typensätze gäbe (Haskell-ähnlicher Pseudocode):

{-#LANGUAGE MultiParamTypeClasses #-}
{-#LANGUAGE FlexibleInstances #-}
{-#LANGUAGE InstanceSigs #-}
{-#LANGUAGE TypeSets #-}

class FromTo a b where
    fromTo:: a->b

instance setfrom (Integral a, Num b). (Integral a, Num b) => FromTo a b where
    fromTo::a->b
    fromTo x = (fromIntegral x)

instance setfrom (RealFrac a, Integral b). (RealFrac a, Integral b) => FromTo a b where
    fromTo::a->b
    fromTo x = (round x)

setfrom C1 a. Hier sollte eine Menge von Typen definiert werden, die Instanzinformationen von verwendenC1 Klasse. Der Compiler sollte prüfen, ob sich Instanzen überschneiden. Die andere mögliche Konstruktion dieser Erweiterung istset (T1,T2,...,TN) a.Damit kann lediglich der Typensatz definiert werden.

UPD 1

Die 1. Lösung könnte auf diese Weise verbessert werden (aber es istfalsch Weg):

{-#LANGUAGE MultiParamTypeClasses #-}
{-#LANGUAGE FlexibleInstances #-}


class FromTo a b where
    fromTo:: a->b

instance FromTo a a where fromTo = id

instance Num b => FromTo Int b where
    fromTo x = fromIntegral x

instance Num b => FromTo Integer b where
    fromTo x = fromIntegral x

instance Integral b => FromTo Float b where
    fromTo x = round x

instance Integral b => FromTo Double b where
    fromTo x = round x

Aber es ist immer noch nicht gut und zusätzlichgibt Überlappungen beim Aufrufen im interaktiven Modus:

*Main> fromTo (10::Double) ::Double

<interactive>:108:1:
    Overlapping instances for FromTo Double Double
      arising from a use of `fromTo'
    Matching instances:
      instance FromTo a a -- Defined at 4.hs:8:10
      instance Integral b => FromTo Double b -- Defined at 4.hs:19:10
    In the expression: fromTo (10 :: Double) :: Double
    In an equation for `it': it = fromTo (10 :: Double) :: Double

Antworten auf die Frage(2)

Ihre Antwort auf die Frage