我有这段代码:
module Coleccion where
data Pila a= Pil [a] deriving (Show,Eq,Ord)
data Cola a= Col [a] deriving (Show,Eq,Ord)
class Coleccion n where
esVacia::n->Bool
insertar::n->a->n
primero::n->a
eliminar:: n->n
size::n->Int;
instance Coleccion (Pila a) where
esVacia (Pil [])= True
esVacia (Pil _ )= False
primero (Pil x) = last x
eliminar (Pil x)= (Pil (init x))
size (Pil []) = 0
size (Pil pila) = length pila;
当我用GHCI编译时,我有:
• Couldn't match expected type ‘a1’ with actual type ‘a’
‘a’ is a rigid type variable bound by
the instance declaration at Coleccion.hs:18:12-29
‘a1’ is a rigid type variable bound by
the type signature for:
primero :: forall a1. Pila a -> a1
at Coleccion.hs:21:5-11
• In the expression: last x
In an equation for ‘primero’: primero (Pil x) = last x
In the instance declaration for ‘Coleccion (Pila a)’
• Relevant bindings include
x :: [a] (bound at Coleccion.hs:21:18)
primero :: Pila a -> a1 (bound at Coleccion.hs:21:5)
我遇到问题的函数是具有与n或预定义类型(Bool,Integer ...)不同的类型的函数,例如,primero。例如,esVacia,size&淘汰赛工作正常。 我不知道声明或实例代码中有什么问题。 谢谢。
答案 0 :(得分:5)
在您的班级声明中,函数insertar
和primera
承诺消费者使用任何类型a
(顺便说一句:你是错过insertar
实施)。但是,在您的类实例中实现它们时,您会尝试使用特定的a
,即Pila
的“内容”。该类的承诺被破坏 - 实例中的函数实际上并不适用于任何类型a
, - 因此编译器会抱怨。
如果您想要完成这项工作,则需要以“ Coleccion
是一个集合的方式声明类n
,该集合包含a
类型的元素,以下是适用于n
和a
“类型的函数。
执行此操作的一种方法是使用关联类型:
class Coleccion n where
type Elemento n
esVacia::n->Bool
insertar::n -> Elemento n -> n
primero::n -> Elemento n
eliminar:: n->n
size::n->Int;
此声明说:“无论谁为某种类型Coleccion
定义n
的实例,都应该提供一种方法来确定该集合的元素类型,{{ 1}}和insertar
应该适用于那种类型,而不是一些随机无关的“。您可以像这样实现它:
primero
在这里,您说:“我的收藏集是instance Coleccion (Pila a) where
type Elemento (Pila a) = a
...
primero (Pil x) = last x
,其元素是Pila a
,这里a
应该如何处理”。< / p>
(注意:您需要primero
扩展名才能执行此操作)
或者,您可以使用功能依赖和双参数类型类:
TypeFamilies
此声明说:“每当您为某种类型class Coleccion n el | n -> el where
...
insertar::n -> el -> n
primero::n -> el
定义Coleccion
的实例时,您还应指定该集合的元素n
是”。 “管道”之后的“箭头”表示集合类型应该明确地确定元素是什么 - 也就是说,您不能让一个集合包含多个不同类型的元素。
然后你实现它:
el
(注意:您需要instance Coleccion (Pila a) a where
...
primero (Pil x) = last x
和FunctionalDependencies
个扩展名
答案 1 :(得分:1)
@Fyodor Soikin解决方案非常棒,这是另一种方法
module Coleccion where
data Pila a= Pil [a] deriving (Show,Eq,Ord)
data Cola a= Col [a] deriving (Show,Eq,Ord)
class Coleccion n where
esVacia::n->Bool
--insertar::n->a->n
primero::n->n
eliminar:: n->n
size::n->Int
instance Coleccion (Pila a) where
esVacia (Pil [])= True
esVacia (Pil _ )= False
primero (Pil xs) = (Pil [(last xs)])
eliminar (Pil xs)= (Pil (init xs))
size (Pil []) = 0
size (Pil xs) = length xs
现在使用Monad,Functor和Applicative,你可以做任何你想做的事情