标准ML中具有多个输入的函子

Ina*_*thi 0 sml functor

高级问题:如何functor在SML中将s与多个参数一起使用?

我看这个这个这个这个(PDF) 。所有这些似乎冲突的条款structurefunctor定义语法,其中没有显示出比一元以外的任何其他functor

细节:我想写的标准ML(你可以看到努力的web服务器在这里),并已决定将其划分成BUFFERPARSERTCPSERVER块。在BUFFERPARSER都只是简单structure秒。使用的想法TCPSERVER是,它处理侦听/接受逻辑,但允许用户通过传递其他两个来指定适当的缓冲/解析策略。

signature TCPSERVER =
sig
    type SockAction
    type Request
    val serve : int -> (Request -> (INetSock.inet,Socket.active Socket.stream) Socket.sock -> SockAction) -> 'u
end

functor Server (Buf : BUFFER) (Par : PARSER) : TCPSERVER =
struct
  type Request = Par.Request
  datatype SockAction = CLOSE | LEAVE_OPEN
  local
  ...
   [eliding more definitions, including calls to Par.* and Buf.* functions]
  ...
  fun serve port serverFn =
      let val s = INetSock.TCP.socket()
      in 
        Socket.Ctl.setREUSEADDR (s, true);
        Socket.bind(s, INetSock.any port);
        Socket.listen(s, 5);
        print "Entering accept loop...\n";
        acceptLoop s [] serverFn
      end
  end
end
Run Code Online (Sandbox Code Playgroud)

以上似乎被smlnj... 接受

- use "server.sml" ;
[opening server.sml]
type Response =
  {body:string, headers:(string * string) list, httpVersion:string,
   responseType:string}
val fst = fn : 'a * 'b -> 'a
val snd = fn : 'a * 'b -> 'b
val a_ = fn : 'a * 'b * 'c -> 'a
val b_ = fn : 'a * 'b * 'c -> 'b
val c_ = fn : 'a * 'b * 'c -> 'c
val curry = fn : ('a * 'b -> 'c) -> 'a -> 'b -> 'c
signature TCPSERVER =
  sig
    type SockAction
    type Request
    val serve : int
                -> (Request
                    -> (INetSock.inet,Socket.active Socket.stream) Socket.sock
                       -> SockAction)
                   -> 'a
  end
functor HTTPServer(Buf: sig
                          type Buffer
                          val readInto : Buffer
                                         -> ('a,Socket.active Socket.stream) 
                                              Socket.sock
                                            -> BufferStatus
                          val new : int -> Buffer
                          val toSlice : Buffer -> Word8ArraySlice.slice
                          val printBuffer : Buffer -> unit
                        end) :
                  sig functor <functor> : <fctsig> end
val it = () : unit
Run Code Online (Sandbox Code Playgroud)

...但是被拒绝mlton

~/projects/serve-sml $ mlton server.mlb
Error: server.sml 23.1. # (line with "functor Server...")
  Syntax error: replacing  FUNCTOR with  FUN.
Error: server.sml 24.1.
  Syntax error: replacing  STRUCT with  ASTERISK.
Error: server.sml 87.1.
  Syntax error found at END.
Error: server.sml 88.0.
  Parse error.
...
Run Code Online (Sandbox Code Playgroud)

另外,我不完全确定评估后如何使用该定义。即使在中smlnj,明显也会失败:

- HTTPServer(DefaultBuffer, DefaultParser) ;
stdIn:1.2-1.12 Error: unbound variable or constructor: HTTPServer
stdIn:2.7-3.1 Error: unbound variable or constructor: DefaultParser
stdIn:1.13-2.5 Error: unbound variable or constructor: DefaultBuffer
- 
Run Code Online (Sandbox Code Playgroud)

谁能告诉我我在做什么错?甚至为我指出了一份很好的文档?

And*_*erg 5

您的Server函子通过currying进行多个论证。这在普通SML中不起作用,因为它没有高阶函子(SML / NJ作为非标准扩展支持该函子)。您需要通过引入辅助结构来使用非咖喱形式,就像您使用元组或以核心语言进行记录一样:

functor Server(X : sig structure Buffer : BUFFER; structure Parser : PARSER end) =
  ...X.Buffer...X.Parser...

structure MyServer =
  Server(struct structure Buffer = MyBuffer; structure Parser = MyParser end)
Run Code Online (Sandbox Code Playgroud)

显然,这是非常笨拙和冗长的,因此至少SML具有上面的一些语法糖,使您可以使辅助结构保持隐式:

functor Server(structure Buffer : BUFFER; structure Parser : PARSER) =
  ...Buffer...Parser...

structure MyServer =
  Server(structure Buffer = MyBuffer; structure Parser = MyParser)
Run Code Online (Sandbox Code Playgroud)

但是,这与当前的SML一样短。