首页 > 解决方案 > 如何跨函数调用链携带值

问题描述

假设我有以下数据结构和功能:

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

我希望能够链接getUserIdhasPermission使用一些语法糖,而不必在Settings链接函数调用时携带实例。像这样的东西:

main = do
  let _permission = Settings{dbName="prod"} >>= getUserId "bob" >> hasPermission
  print _permission

这(显然)不起作用。

这个有什么首选模式吗?

标签: haskell

解决方案


在我看来,解决这些问题的最简单方法是使用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。通常,我认为第一个选项(部分应用程序)更简单且更易于理解。


推荐阅读