我有这样的代码:
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 & eliminar运行良好。我不知道声明或实例代码有什么问题。谢谢。
发布于 2017-12-11 17:30:31
在类声明中,函数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 __定义一个实例,都应该提供一种方法来确定该集合的元素类型,而insertar和primero应该处理该类型,而不是在一些随机的无关类型上工作”。您可以这样实现它:
instance Coleccion (Pila a) where
    type Elemento (Pila a) = a
    ...
    primero (Pil x) = last x在这里,您会说:“我的收藏是Pila a__,它的元素是a__,下面是primero应该如何处理的”。
(注意:您需要使用TypeFamilies扩展来完成此操作)
Alternatively,您可以使用函数依赖项和双参数类型类:
class Coleccion n el | n -> el where
    ...
    insertar::n -> el -> n
    primero::n -> el这个声明说:“每当您为某个类型的Coleccion __定义一个实例时,您还应该指定该集合的元素el是什么”。“管道”后面的“箭头”表示,集合类型应该明确地确定元素是什么--也就是说,不能让一个集合包含几种不同类型的元素。
然后将其实现如下:
instance Coleccion (Pila a) a where
    ...
    primero (Pil x) = last x(注意:为此您需要FunctionalDependencies和MultiParamTypeClasses扩展)
发布于 2017-12-11 18:16:16
@Fyodor解决方案是很棒的--这是另一种方法
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,函子和应用程序,你可以做任何你想做的事。
https://stackoverflow.com/questions/47758065
复制相似问题