假设我们有一个模块负责向Flickr发出api请求.我不想将api密钥硬编码到Flickr模块中.Api密钥可以通过ajax请求获取.
现在,Flickr模块中的每个函数都接受apiKey作为其参数.但它并不是那么酷的传递那个api键.有没有简单的方法来解决这个问题?或者是否可以在模块之间共享一些值而不传递每个函数.
module Flickr where
searchPhotos : String -> String -> ...
searchPhotos apiKey query = ...
getPhotoInfo : String -> String -> ...
getPhotoInfo apiKey photoId = ...
anotherOne : String -> ...
anotherOne apiKey = ...
Run Code Online (Sandbox Code Playgroud)
更新:我到目前为止尝试的是部分应用功能.最后我把apiKey作为参数.但现在我必须传递这个功能,还有其他想法吗?
makeFlickrRequest : (String -> String -> a) -> a
makeFlickrRequest flickrMethod = flickrMethod "myApikey" "mySecret"
photosSearch : String -> String -> String -> ...
photosSearch query apiKey secret =
makeHTTPCallhere ...
-- Usage:
makeFlickrRequest (photosSearch "haskell")
Run Code Online (Sandbox Code Playgroud)
使用阅读器monad,您可以隐藏所有功能(API密钥)的常见"环境".这是一个简单的例子:
第一,
import Control.Monad.Reader
Run Code Online (Sandbox Code Playgroud)
然后,一些类型的别名来帮助提高可读性.这里值得注意的是FlickrRequest a部分 - 它表示一个flickr请求,它返回一个类型的值a:
type APIKey = String
type Photo = String
type PhotoInfo = String
type FlickrRequest a = Reader APIKey a
Run Code Online (Sandbox Code Playgroud)
以下是搜索照片和获取某些照片信息的两个虚拟实现:
searchPhotos :: String -> FlickrRequest [Photo]
searchPhotos query = do
apiKey <- ask
return ["<Photo for query " ++ query ++ " (api key " ++ apiKey ++ ")>"]
getPhotoInfo :: Photo -> FlickrRequest PhotoInfo
getPhotoInfo photo = do
apiKey <- ask
return $ "This is the photo information for photo " ++ photo ++ " (" ++ apiKey ++ ")"
Run Code Online (Sandbox Code Playgroud)
请注意,API密钥通过FlickrRequest阅读器隐式传递.在这些函数中,您可以使用访问该环境(您可以"阅读"环境)ask.当组合所有在相同环境中运行的功能时,它的美妙之处在于,例如:
-- This could be just `searchPhotos "*" >>= mapM getPhotoInfo` but I don't
-- want to obscure things unnecessarily.
allPhotoInfos :: FlickrRequest [PhotoInfo]
allPhotoInfos = do
photos <- searchPhotos "*"
sequence (map getPhotoInfo photos)
Run Code Online (Sandbox Code Playgroud)
我们先打电话searchPhotos然后申请getPhotoInfo所有找到的照片.注意API密钥是如何无处可见的,它被隐含地传递了!
最后,要运行整个事情,您可以使用该runReader功能.就像是
main :: IO ()
main = do
let myAPIKey = "someAPIKey"
print (runReader allPhotoInfos myAPIKey)
Run Code Online (Sandbox Code Playgroud)