Haskell не получает мою функциональную зависимость - PullRequest
2 голосов
/ 15 января 2020

Я пытаюсь создать класс типа очереди, который реализует базовое c поведение очереди. Мой код выглядит следующим образом:

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}

data QueueA a = QueueA { front :: [a], rear :: [a] }

class Queue a b | a -> b where

  empty         :: a
  null          :: a -> Bool
  head          :: a -> Maybe b
  tail          :: a -> Maybe a
  toList        :: a -> [b]
  (|>)          :: a -> b -> a

instance Queue (QueueA a) where      

  empty = QueueA [] []

  null (QueueA [] []) = True
  null _ = False

  head (QueueA [] []) = Nothing
  head (QueueA (x:xs) _) = Just x

  tail (QueueA [] []) = Nothing
  tail (QueueA (x:xs) (y:ys)) = Just $ QueueA (xs ++ [y]) ys

  toList (QueueA x y) = x ++ y

  (|>) (QueueA x y) e = if (length x > length y) then QueueA (init $ e : x) ((last x) : y) else QueueA (e : x) y

К сожалению, когда я пытаюсь скомпилировать код, gh c говорит мне следующее:

queue.hs:15:10: error:
    • Expecting one more argument to ‘Queue (QueueA a)’
      Expected a constraint,
        but ‘Queue (QueueA a)’ has kind ‘* -> Constraint’
    • In the instance declaration for ‘Queue (QueueA a)’
   |
15 | instance Queue (QueueA a) where 
   |          ^^^^^^^^^^^^^^^^

Я не получаю сообщение хоть. Все, что я знаю, это то, что шаблон для очереди в моем объявлении экземпляра должен быть верным, потому что он в точности соответствует указанному выше в моем типе данных. Я попробовал несколько вариантов моего объявления экземпляра, но безрезультатно. Я просто что-то пропускаю? Как мне сделать это компилируемым?

Ответы [ 2 ]

4 голосов
/ 15 января 2020

Экземплярам нужно столько же параметров, сколько и соответствующему классу. Тем не менее, вы создали класс с 2 параметрами и соответствующий экземпляр только с 1. Чтобы его скомпилировать, вы можете сделать instance Queue (QueueA a) a where вместо instance Queue (QueueA a) where. (Вам также понадобится расширение FlexibleInstances.)

2 голосов
/ 15 января 2020

Вам не нужно несколько параметров для класса. Вместо этого класс должен принимать тип высшего порядка в качестве аргумента, а не конкретный тип.

class Queue t where
    empty :: t a
    null :: t a -> Bool
    head :: t a -> Maybe a
    tail :: t a -> Maybe (t a)
    toList :: t a -> [a]
    (|>) :: t a -> a -> t a

QueueA сам по себе имеет экземпляр Queue, а не QueueA a.

instance Queue QueueA where
  -- same as above
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...