Haskell:无法将预期类型'a1'与实际类型'a'匹配

时间:2017-12-11 17:19:25

标签: haskell

我有这段代码:

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&淘汰赛工作正常。 我不知道声明或实例代码中有什么问题。 谢谢。

2 个答案:

答案 0 :(得分:5)

在您的班级声明中,函数insertarprimera承诺消费者使用任何类型a(顺便说一句:你是错过insertar实施)。但是,在您的类实例中实现它们时,您会尝试使用特定的a,即Pila的“内容”。该类的承诺被破坏 - 实例中的函数实际上并不适用于任何类型a, - 因此编译器会抱怨。

如果您想要完成这项工作,则需要以“ Coleccion是一个集合的方式声明类n,该集合包含a类型的元素,以下是适用于na “类型的函数。

执行此操作的一种方法是使用关联类型

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,你可以做任何你想做的事情