2015-06-10 37 views
0

你好,我需要創建一個類,其中包含一個方法prize'計算一些分數。我想實例的情況下,我得到一個Order,以後我將不得不再比如如果我得到一個[Order],這是代碼:Haskell類的誤解

class Ped a where 
    prize' :: Fractional b => a -> b 

instance (Integral n, Fractional p) => Ped (Order n p) where 
    prize' x = prizeOrder x 

data (Integral c,Fractional p) => Product c p 
    = Prod c String p 
    deriving (Show, Read) 

data (Integral n, Fractional p) => Order n p 
    = PdMult (Product n p) n 
    | PdUnit (Product n p) 
    deriving (Show, Eq) 

prize :: (Fractional p, Integral c) =>(Product c p) -> p 
prize (Prod _ _ x) = x 

prizeOrder :: (Fractional p, Integral c) => (Order c p) -> p 
prizeOrder (PdMult p n) = (prize p) * (fromIntegral n) 
prizeOrder (PdUnit p) = prize p 

前奏說:

Could not deduce (p ~ b) 
from the context (Integral n, Fractional p) 
bound by the instance declaration 
at src\Funciones.hs:6:10-55 
or from (Fractional b) 
bound by the type signature for 
    prize' :: Fractional b => Order n p -> b 
at src\Funciones.hs:7:5-11 
`p' is a rigid type variable bound by 
    the instance declaration 
    at src\Funciones.hs:6:10 
`b' is a rigid type variable bound by 
    the type signature for prize' :: Fractional b => Order n p -> b 
    at src\Funciones.hs:7:5 
Expected type: Order b 
    Actual type: Order n p 
Relevant bindings include 
    x :: Order n p 
    (bound at src\Funciones.hs:7:13) 
    prize' :: Order n p -> b 
    (bound at src\Funciones.hs:7:5) 
In the first argument of `prizeOrder', namely `x' 
In the expression: prizeOrder x 
+2

首先,不要將類限制放在數據類型上。如果您需要GADT的功能,但看起來這不是您需要的解決方案。 – bheklilr

+1

問題是你的班級說:我可以把它轉換成你想要的任何'分數',而數據明確地根據你所做的決定來限制它。 –

+0

我已經完成了一個使用它們的大程序,它能正常工作,但它第一次在程序中創建一個類:) – KannaKiski

回答

1

的問題是您的class定義給出了額外的自由度,您的instance未能提供。在你的類,你聲明:

class Ped a where 
    prize' :: Fractional b => a -> b 

這意味着程序員可以選擇他/她想要什麼Fraction bb

現在如果我們查看到您的實例:

instance (Integral n, Fractional p) => Ped (Order n p) where 
    prize' x = prizeOrder x 

在這裏,您說prize'取決於prizeOrder。然而,prizeOrder函數簽名:

prizeOrder :: (Fractional p, Integral c) => (Order c p) -> p 

這意味着你不能選擇b可言。如果我使用prize',並且預期返回類型爲Float,那麼Ped將會接受此結果,但不會由數據結構Order Double Int接受。

使用多參數類可以「解決」這個,你把bclass簽名:

class Ped a b where 
    prize' :: a -> b 

接下來,你需要用第二類參數定義實例,以保證輸出爲p

instance (Integral n, Fractional p) => Ped (Order n p) p where 
    prize' x = prizeOrder x 

您需要激活一些額外的GHC特點,充分鱈魚Ë會讀到這樣:

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

class Ped a b where 
    prize' :: a -> b 

instance (Integral n, Fractional p) => Ped (Order n p) p where 
    prize' x = prizeOrder x 

data (Integral c,Fractional p) => Product c p 
    = Prod c String p 
    deriving (Show, Read) 

data (Integral n, Fractional p) => Order n p 
    = PdMult (Product n p) n 
    | PdUnit (Product n p) 
    deriving (Show) 

prize :: (Fractional p, Integral c) =>(Product c p) -> p 
prize (Prod _ _ x) = x 

prizeOrder :: (Fractional p, Integral c) => (Order c p) -> p 
prizeOrder (PdMult p n) = (prize p) * (fromIntegral n) 
prizeOrder (PdUnit p) = prize p 

但是,作爲@bheklilr說,不要使用「類約束的數據類型」。此外,最好問他/她是否支付使用class

+0

非常感謝,我以前試過,但我不知道如何激活這些功能y複製您的代碼和前奏告訴我: 'Ped'類參數太多 (使用MultiParamTypeClasses來允許多參數類) 在'Ped'的類聲明中 – KannaKiski

+0

@KannaKiski:使用'{ - #'和'# - }'之間的指令。這些不是評論。 –

+0

我已經做到了,但它也是一樣的東西......它可能是Eclipse嗎? – KannaKiski