高级问题:如何functor在SML中将s与多个参数一起使用?
我看这个,这个,这个和这个(PDF) 。所有这些似乎冲突的条款structure或functor定义语法,其中没有显示出比一元以外的任何其他functor。
细节:我想写的标准ML(你可以看到努力的web服务器在这里),并已决定将其划分成BUFFER,PARSER和TCPSERVER块。在BUFFER和PARSER都只是简单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)
谁能告诉我我在做什么错?甚至为我指出了一份很好的文档?
您的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一样短。