使用一组默认值(elm或haskell)初始化模块

Umu*_*dik 3 haskell elm

假设我们有一个模块负责向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)

Fre*_*abe 6

使用阅读器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)