我正在尝试编写一个 Haskell 模块,该模块使用库 haxr 为远程 XML-RPC API 定义函数。 .以下是 haxr 的文档建议您定义调用 examples.add
的 Haskell 函数的方式。在服务器上 url
:
add :: String -> Int -> Int -> IO Int
add url = remote url "examples.add"
像这样调用:
server = "http://localhost/~bjorn/cgi-bin/simple_server"
add server x y
如果我有一个或两个 XML-RPC 方法,这对我来说似乎没问题(那时我不需要单独的模块)。但是,
server
的重复在代码中是一个问题,因为我有接近 100 个函数。我无法定义 server
在模块中,像这样:someRemote :: Remote
someRemote = remote "http://example.com/XMLRPC"
add :: Int -> Int -> IO Int
add = someRemote "examples.add"
因为如果要灵活地使用它的代码,就不能对 URL 进行硬编码。我也无法定义
someRemote
作为函数的参数,因为它具有相同的重复问题。Haxr's examples没有提供有关如何解决此问题的线索。
我通常用命令式 OOP 语言(即 Java、Python)编写程序。如果我使用这些语言,我将定义一个带有构造函数的类,该构造函数采用
server
,以及所有使用对象实例的函数server
变量,而不是询问调用代码。我在 Haskell 中寻找了与此等效的内容,但我似乎不知道找到它的正确关键字。类型类似乎不是答案。我可以编写一个返回部分应用函数的高阶函数,但解包这些函数会更难看。
最佳答案
我不太确定“服务器重复”实际上是不是很糟糕。当然,您永远不应该复制冗长的文字,但是对于不会使代码困惑且易于替换的单个变量名,这应该不是什么大问题。
但是当然,您可以通过将共享变量附加到您正在使用的 monad 来轻松避免这种重复,类似于您将其附加到 OO 类对象的方式。这叫读者。
import Control.Monad.Trans.Reader
type RemoteIO = ReaderT String IO -- or perhaps `ReaderT Remote IO`
add :: Int -> Int -> RemoteIO Int
add x y = do
url <- ask
lift $ remote url "examples.add" x y
关于haskell - 如何干净地定义包含具有公共(public)变量参数的函数的 Haskell 模块?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25326264/