3

I am trying to implement a concurrent list using CML extensions of Standard ML but i am running into errors that are probably to do with my being a newbie in Standard ML. I have implemented the clist as having an input and output channel and I store the list state in a loop. However my code does not compile and gives errors below

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

This is the signature file

signature CLIST =
  sig
    type 'a clist

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

Errors I am getting:

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}
spydadome
  • 325
  • 2
  • 9
  • 2
    Where is the CLIST signature? It is type errors you are getting, so it would be nice to have them available. The main problem is that your 'head' operation does not deconstruct the list I guess. – I GIVE CRAP ANSWERS Feb 25 '11 at 13:32
  • I just repasted the error section as I was using a commented out file and lines were wrong. I also included the signature – spydadome Feb 25 '11 at 13:44

1 Answers1

0

So your problem is in your definition of clist

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

This is saying that the request channel takes in a request of 'a and replies with a 'a. This is not consistent with your implementation. When you send a CONS x request on the channel, you are saying add x of type 'a to the list, but when you send a HEAD request, you are saying give me back the entire list. Thus, a CONS request should take a 'a and a HEAD request should return a 'a list. You can fix your problem by changing your clist definition to

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

I would also suggest changing your definition of cnil to a unit -> 'a clist function, this way you can create distinct concurrent lists.

For example:

val l1 = Clist.cnil()  
val l2 = Clist.cnil() (*cons'ing onto l2 won't affect l1*)
Matt
  • 4,029
  • 3
  • 20
  • 37
  • Your explanation of the problem seems correct, but your proposed solution seems wrong to me. Surely the right fix is for `HEAD` to return just the head of the list? That's what the name `HEAD` implies, and it's also implied by the definition of `hd` in terms of `HEAD`. (Note that, in order for the signature to match, `hd` has to have type `'a clist -> 'a`. This would not happen if `recv replyCh` had type `'a list`.) – ruakh Aug 17 '15 at 05:15