2016-07-18 12 views
1

Ist es möglich, die folgenden zwei Funktionen in Haskell zu einer polymorphen Funktion zu kombinieren?Wie konvertiert man (Num a) => a in Haskell?

mutiplyByTwoI :: Int -> Float 
mutiplyByTwoI x = fromIntegral x * 2.0 

mutiplyByTwoF :: Float -> Float 
mutiplyByTwoF x = x * 2.0 

Ich versuchte Num a, aber ich konnte nicht einen Weg zu konvertieren Num a zu Float finden.

mutiplyByTwo :: (Num a) => a -> Float 
mutiplyByTwo = undefined 
+1

Sie können 'fromIntegral' versuchen, aber es fügt eine zusätzliche Einschränkung von' Integral' hinzu – pdexter

+0

@pdexter Aber Float ist keine Instanz von Integral. –

+1

Können Sie Ihre Frage anders formulieren? Das Thema sagt "How to Convert (Num a) => a zu Float", aber Ihre Frage fragt, wie man eine generische Funktion schreibt, um Num um 2 zu multiplizieren. Was genau wollen Sie tun? – pdexter

Antwort

3

Sie können

byTwo :: Real a => a -> Float 
byTwo x = 2 * realToFrac x 

schreiben, die auf beide Typen spezialisiert sein können Sie, Int -> Float und Float -> Float anfordern.

8

Nicht jede Instanz von Num hat eine vernünftige Umstellung auf Float. Für ein einfaches (ha ha) Beispiel betrachtet komplexe Zahlen:

-- represented in rectangular coordinates 
data Complex = Complex { real :: Float, imaginary :: Float } deriving (Eq, Ord, Show, Read) 

instance Num Complex where 
    Complex u v + Complex x y = Complex (u + x) (v + y) 
    Complex u v * Complex x y = Complex (u * x - v * y) (v * x + u * y) 
    negate (Complex u v) = Complex (negate u) (negate v) 
    -- etc 

Offensichtlich gibt es keine Möglichkeit, ein Complex zu einem Float ohne Wegwerfen Informationen zu konvertieren: Float s leben (eine Untergruppe von) die wirklichen Linie während komplexen Zahlen leben auf der komplexen Ebene. Es gibt keine Funktion toFloat :: Num a => a -> Float, die für alle Instanzen von Num funktioniert.

+1

'Complex' sind nicht gut' Num's weil jede 'Num' ein' signum' haben soll (ob das eine gute oder eine schlechte Sache ist, werde ich hier nicht streiten;) –

+0

Danke! Jetzt verstehe ich, warum es kein 'toFloat :: Num a => a -> Float gibt. –

+5

@nm Die [Docs] (http://hackage.haskell.org/package/base-4.9.0.0/docs/Prelude.html#v:signum) sagen nichts restriktiver als _Die Funktionen 'abs' und' signum' sollte das Gesetz erfüllen: abs x * signum x == x'_. Es gibt eine sinnvolle Implementierung dieses Gesetzes für komplexe Zahlen: "abs (A e^iφ) = A" und "signum (A e^iφ) = e^iφ". Ich habe es aus meiner Antwort weggelassen, weil ich mich nicht darum kümmern konnte, das Trigon zu machen, um von rechteckig zu polar zu konvertieren. –