Search code examples
socketsselectsml

Type error calling select Standard ML


I'm trying to call Socket.select to deal with some sockets. It seems like the following minimal snippet from my code should work...

fun descs ss = map Socket.sockDesc ss

fun selecting server clients =
    let val { ss, ws, cs } = Socket.select {
        rds = descs [server],
        wds = descs [],
        exs = descs clients,
        timeout = (SOME (Time.fromSeconds 10))
        }
    in
    (ss, ws, cs)
    end

... but doesn't when I evaluate it in SML/NJ:

Standard ML of New Jersey v110.76 [built: Thu Feb 19 00:37:13 2015]
- fun descs ss = map Socket.sockDesc ss ;;
[autoloading]
[library $SMLNJ-BASIS/basis.cm is stable]
[autoloading done]
val descs = fn : ('a,'b) Socket.sock list -> Socket.sock_desc list
- fun selecting server clients =
    let val { ss, ws, cs } = Socket.select {
        rds = descs [server],
        wds = descs [],
        exs = descs clients,
        timeout = (SOME (Time.fromSeconds 10))
        }
    in
    (ss, ws, cs)
    end ;;
= = = = = = = = = [autoloading]
[autoloading done]
stdIn:3.13-8.7 Error: operator and operand don't agree [tycon mismatch]
  operator domain: {exs:Socket.sock_desc list, rds:Socket.sock_desc list,
                    timeout:Time.time option, wrs:Socket.sock_desc list}
  operand:         {exs:Socket.sock_desc list, rds:Socket.sock_desc list,
                    timeout:Time.time option, wds:Socket.sock_desc list}
  in expression:
    Socket.select
      {rds=descs (server :: nil),wds=descs nil,exs=descs clients,
       timeout=SOME (Time.fromSeconds 10)}
- 
- 

Could anyone point out what I'm doing wrong?


Solution

  • (Thanks to bgates from #sml for pointing me in the right direction here)

    Two problems with the above. Firstly, I had a typo in the constructor name in the call to Socket.select.

    ...
     rds = descs [server],
     wrs = descs [],  (* `wrs` instead of `wds` here *)
     exs = descs clients,
    ...
    

    Secondly, when pattern-matching on records, you must use the slot-names of the record rather than arbitrary symbols. So

    ...
        let val { ss, ws, cs } = Socket.select {
    ...
    

    should actually be

    ...
        let val { rds, wrs, exs } = Socket.select {
    ...
    

    With those changes...

    Standard ML of New Jersey v110.76 [built: Thu Feb 19 00:37:13 2015]
    - fun descs ss = map Socket.sockDesc ss ;;
    [autoloading]
    [library $SMLNJ-BASIS/basis.cm is stable]
    [autoloading done]
    val descs = fn : ('a,'b) Socket.sock list -> Socket.sock_desc list
    - fun selecting server clients =
        let val { rds, exs, wrs } = Socket.select {
            rds = descs [server],
            wrs = descs [],
            exs = descs clients,
            timeout = (SOME (Time.fromSeconds 10))
            }
        in
        (rds, wrs, exs)
        end ;;
    = = = = = = = = = [autoloading]
    [autoloading done]
    val selecting = fn
      : ('a,'b) Socket.sock
        -> ('c,'d) Socket.sock list
           -> Socket.sock_desc list * Socket.sock_desc list * 
              Socket.sock_desc list
    -