haskell - 如何跨函数调用链携带值
问题描述
假设我有以下数据结构和功能:
data Settings = Settings { dbName :: String } deriving Show
-- username to user id lookup
getUserId :: Settings -> String -> Int
getUserId settings username = 1
-- checks permission for a given user id
hasPermission :: Settings -> Int -> Bool
hasPermission settings userId = True
我希望能够链接getUserId
并hasPermission
使用一些语法糖,而不必在Settings
链接函数调用时携带实例。像这样的东西:
main = do
let _permission = Settings{dbName="prod"} >>= getUserId "bob" >> hasPermission
print _permission
这(显然)不起作用。
这个有什么首选模式吗?
解决方案
在我看来,解决这些问题的最简单方法是使用partial application,如下所示:
main = do
let settings = Settings { dbName="prod" }
let getUserId' = getUserId settings
let hasPermission' = hasPermission settings
let _permission = hasPermission' $ getUserId' "bob"
print _permission
但是,如果你把 'common' 参数放在最后,你也可以使用内置的reader monad实例:
main :: IO ()
main = do
let getPermission = (flip getUserId) "bob" >>= (flip hasPermission)
print $ getPermission $ Settings { dbName="prod" }
这getPermission
是一个类型为 的本地函数Settings -> Bool
。通常,我认为第一个选项(部分应用程序)更简单且更易于理解。
推荐阅读
- python - 如何通过在 Discord.py 3.6 上相乘将 asyncio.sleep 秒数转换为 1 分钟或 1 小时
- google-apps-script - 使用应用脚本 api 从另一个谷歌表访问谷歌表
- expo - Expo启动问题,无法读取配置
- python - 按字符对字符串列表进行排序
- c# - 是什么让我在 C# 中的 SSE 上绊倒?
- javascript - 异常值:字段 'id' 需要一个数字,但得到了
- c# - VLC.Dotnet.WPF 控件拉伸纵向视频。如何让控件不拉伸视频
- php - 如何正确地将 Wordpress 中的某些 Elementor css 文件出列?
- reactjs - 在反应中删除任务杂物
- java - 使用微调器时如何添加图像