簡體   English   中英

Haskell:無法將預期類型“ a1”與實際類型“ a”匹配

[英]Haskell: Couldn't match expected type ‘a1’ with actual type ‘a’

我有以下代碼:

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運行正常。 我不知道聲明或實例代碼有什么問題。 謝謝。

在你的類聲明,功能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;

該聲明說:“ 無論是為某個類型n定義Coleccion實例的人,都應提供一種方法來確定該集合的元素的類型,並且insertarprimero應在該類型上工作,而不是在某些隨機無關的類型上工作。 ”。 您可以這樣實現:

instance Coleccion (Pila a) where
    type Elemento (Pila a) = a
    ...
    primero (Pil x) = last x

在這里,您說:“ 我的收藏集是Pila a ,它的元素是a ,這就是primero在其上的工作方式 ”。

(注意:您需要TypeFamilies擴展名才能執行此操作)

或者 ,您可以使用函數依賴項和兩參數類型類:

class Coleccion n el | n -> el where
    ...
    insertar::n -> el -> n
    primero::n -> el

該聲明說:“ 每當為某些類型n定義Coleccion實例時,還應指定該集合的元素el是什么 。” “管道”之后的“箭頭”表示,集合類型應明確確定元素是什么-也就是說,您不能讓一個集合包含幾種不同類型的元素。

然后,您可以像這樣實現它:

instance Coleccion (Pila a) a where
    ...
    primero (Pil x) = last x

(注意:為此,您需要FunctionalDependenciesMultiParamTypeClasses擴展)

@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您可以做任何您想做的事

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM