簡體   English   中英

如何使用公共變量參數清晰地定義包含函數的Haskell模塊?

[英]How to cleanly define a Haskell module containing functions with a common variable parameter?

我正在嘗試編寫一個Haskell模塊,該模塊使用庫haxr定義遠程XML-RPC API的函數。 以下是haxr的文檔建議您如何在url上定義一個調用examples.add的Haskell函數:

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的例子沒有提供如何解決這個問題的線索。

我通常用命令式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中的OOP方法:

module MyServer (
    Server, -- don't expose constructor
    newServer,
    add,
) where

data Server = Server String

newServer :: String -> IO Server
newServer = return . Server

add :: Server -> Int -> Int -> IO Int
add (Server url) = remote url "examples.add"

您每次撥打電話時仍然必須通過服務器,但現在您可以更改服務器的表示(例如,使其成為持久連接的句柄)。

此外,您可以使用reader monad來隱式傳遞服務器:

class MonadServer m where
    withServer :: (Server -> m a) -> m a

instance MonadServer (ReaderT Server m) where
    withServer f = ReaderT (\server -> runReaderT (f server) server)

add :: (MonadIO m, MonadServer m) => Int -> Int -> m Int
add x y = withServer (\(Server url) -> liftIO $ remote url "examples.add" x y)

通過使MonadServer成為類型類,可以擴展您使用的任何讀者monad以支持隱式Server參數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM