您好我需要创建一个包含名为prize'
的方法的类,该方法计算一些分数。我想要实例以防我得到Order
,稍后我将再次实例以防我得到[Order]
,这是代码:
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
Prelude说:
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
答案 0 :(得分:1)
问题在于,class
定义提供了额外的自由度,而您的instance
无法提供。在你的班上你说:
class Ped a where
prize' :: Fractional b => a -> b
这意味着程序员可以为他/她想要的Fraction b
选择b
。
现在,如果我们查看您的实例:
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
会接受。
您可以使用多参数类“解决”这个问题,您可以使用b
签名中的class
:
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
是否有用。