2016-10-24 11 views
0

Hallo ich bin neu in Haskell und ich habe Probleme.Kann nicht erwartet Typ d mit tatsächlichen Typ b

Ich möchte ein Verfahren schaffen, die für eine Partida und für eine Liste von Partidas (Facturas) zu tun, so haben wir diesen Code gültig ist:

data Bebida a b where { 
     Bebida::(Integral a, Fractional b)=>{codigo::a, nombre::[Char], precio::b } -> Bebida a b 
    } 

data Partida a b c where { 
    ParMult:: (Integral a, Integral c, Fractional b) => {cantidad::c, bebida::Bebida a b} -> Partida a b c; 
    ParUnit:: (Integral a, Integral c, Fractional b) => {bebida::Bebida a b} -> Partida a b c 
    } 

type Factura a b c = [Partida a b c] 

class Preciable a where 
precioe :: (Fractional d) => a -> d 

instance (Integral a, Fractional b, Integral c) => Preciable (Partida a b c) where 
precioe (ParMult n b) = (fromIntegral(n)*(precio b)) 
precioe (ParUnit b) = (precio b) 

instance (Integral a, Integral c, Fractional b, Eq b) => Preciable (Factura a b c) where 
precioe f = sum [precioe x | x<-f] 

Ich weiß nicht, warum gibt mir diese Fehler. Kann mir jemand helfen, mir zu sagen, warum Haskell mir diesen Fehler gibt?

Vielen Dank für Ihre Hilfe !!

+1

'precioe :: (Fractional d) => a -> d' verspricht für Arbeit * jede * 'd' überhaupt, durch den Code gewählt * Aufruf * 'precioe'. Ihre Implementierungen geben dem Anrufer nicht die Freiheit, sondern erzwingen, dass "d" der Typ ist, der in Ihren "Partida" - und "Factura" -Typen gebacken wird. – amalloy

Antwort

3

Das Problem wird precioe soll jede Fractionald zurückzukehren (Double, Rational etc.). Der Anrufer von precioe kann entscheiden, was es ist.

Ihre Instanzen Preciable Rückkehr etwas, das Fractional (b), aber nicht unbedingt die Fractional, dass der Anrufer von precioe wollte (d) ist. Glücklicherweise gibt es eine Möglichkeit, jegliche Fractional Zahl d mit fromRational :: Fractional d => Rational -> d

Sie machen b zu einem Rational mit der Real Klasse kann zu erstellen:

class (Num a, Ord a) => Real a where 
    toRational :: a -> Rational 

Es gibt eine Funktion, die diese beiden kombiniert, die auch Regeln verwendet umschreiben für eine schnellere Umwandlungen zwischen bestimmten Typen:

realToFrac :: (Real a, Fractional b) => a -> b 
realToFrac = fromRational . toRational 

eine Real ConstraintHinzufügenlässt Ihre Schreib die Instanzen mit realToFrac:

instance (Integral a, Real b) => Preciable (Partida a b c) where 
    precioe (ParMult n b) = fromIntegral n * realToFrac (precio b) 
    precioe (ParUnit b) = realToFrac (precio b) 

instance (Integral a, Real b) => Preciable (Factura a b c) where 
    precioe f = sum [precioe x | x <- f] 
Verwandte Themen