Стандартный неправильный оператор ML / CML - ошибка операнда

Я пытаюсь реализовать параллельный список с использованием расширений CML для Standard ML, но я сталкиваюсь с ошибками, которые, вероятно, связаны с тем, что я новичок в Standard ML. Я реализовал clist как имеющий канал ввода и вывода, и я сохраняю состояние списка в цикле. Однако мой код не компилируется и выдает ошибки ниже

structure Clist : CLIST = 
struct
  open CML

  datatype 'a request = CONS of 'a | HEAD

  datatype 'a clist = CLIST of { reqCh : 'a request chan, replyCh : 'a chan }

  (* create a clist with initial contents l *)
  val cnil = 
    let
      val req = channel()
      val reply = channel()
      fun loop l = case recv req of
          CONS x =>
            (loop (x::l))
        | 
          HEAD => (send(reply, l); loop l)
    in
      spawn(fn () => loop nil);
      CLIST {reqCh=req,replyCh=reply}
    end

  fun cons x (CLIST {reqCh, replyCh})=  
    (send (reqCh, CONS x); CLIST {reqCh = reqCh, replyCh = replyCh})

  fun hd (CLIST {reqCh, replyCh}) = (send (reqCh, HEAD); recv replyCh)  
end

Это файл подписи

signature CLIST =
  sig
    type 'a clist

    val cnil : 'a clist
    val cons : 'a -> 'a clist -> 'a clist
    val hd : 'a clist -> 'a
  end

Я получаю ошибки:

clist.sml:21.4-21.35 Error: operator and operand don't agree [circularity]
  operator domain: {replyCh:'Z list chan, reqCh:'Z list request chan}
  operand:         {replyCh:'Z list chan, reqCh:'Z request chan}
  in expression:
    CLIST {reqCh=req,replyCh=reply}

person spydadome    schedule 25.02.2011    source источник
comment
Где подпись CLIST? Вы получаете ошибки типа, поэтому было бы хорошо, если бы они были доступны. Основная проблема в том, что ваша «голова», я думаю, не разрушает список.   -  person I GIVE CRAP ANSWERS    schedule 25.02.2011
comment
Я просто переделал раздел ошибок, так как использовал закомментированный файл, а строки были неправильными. Я также поставил подпись   -  person spydadome    schedule 25.02.2011


Ответы (1)


Итак, ваша проблема в вашем определении clist

datatype 'a clist = CLIST of { reqCh : 'a request chan, replyCh : 'a chan }

Это означает, что канал запроса принимает запрос 'a и отвечает 'a. Это не соответствует вашей реализации. Когда вы отправляете CONS x запрос на канал, вы говорите добавить x типа 'a в список, но когда вы отправляете HEAD запрос, вы говорите вернуть мне весь список. Таким образом, запрос CONS должен принимать 'a, а запрос HEAD должен возвращать 'a list. Чтобы решить проблему, измените определение clist на

datatype 'a clist = CLIST of { reqCh : 'a request chan, replyCh : 'a list chan }

Я также предлагаю изменить ваше определение cnil на функцию unit -> 'a clist, чтобы вы могли создавать отдельные параллельные списки.

Например:

val l1 = Clist.cnil()  
val l2 = Clist.cnil() (*cons'ing onto l2 won't affect l1*)
person Matt    schedule 05.06.2015
comment
Ваше объяснение проблемы кажется правильным, но предложенное вами решение мне кажется неправильным. Разумеется, правильное решение для HEAD - возвращать только начало списка? Это то, что подразумевает имя HEAD, и это также подразумевается определением hd в терминах HEAD. (Обратите внимание, что для соответствия подписи hd должен иметь тип 'a clist -> 'a. Этого не произошло бы, если бы recv replyCh имел тип 'a list.) - person ruakh; 17.08.2015