我有一个简单的问题,但是我找不到合适的解决方案。 我有这样的功能:
getFoos :: Maybe Int
-> Maybe Int
-> Maybe Int
-> [(String, Int)]
getFoos ma mb mc = ...
我想创建以下数组:[("A": 1), ("B": 2), ("C": 3)]
。
但这仅是三个参数都是Just!如果一个或多个为Nothing,它们将不会出现在结果数组中。
有什么优雅的方法可以做到这一点吗?
有关信息,我功能的真正签名是:
getQuerySelect :: Maybe Token
-> Maybe DeviceId
-> Maybe SensorId
-> Maybe Int
-> Maybe Int
-> Maybe Int
-> Maybe UTCTime
-> Maybe UTCTime
-> [(String, String)]
用于MongoDB数据库查询。
到目前为止,我的设计是
getQuerySelect mdev msen ... = do
let selDev = [("device_id", dev) | (Just (DeviceId dev)) <- [mdev]]
let selSen = [("sensor_id", sen) | (Just (SensorId sen)) <- [msen]]
...
return $ selDev <> selSen <> ...
有效,但在我看来还是有点尴尬。
答案 0 :(得分:3)
如果您希望它“很好地扩展以容纳更多Maybes”,则首先使用数组:
getFoosArr :: [Maybe Int] -> [(String, Int)]
实现可以是例如:
getFoosArr = catMaybes . zipWith (\a -> fmap (a,)) [A..]
首先我们用字母 1 标记每个Maybe Int
,然后只需用Just
过滤掉catMaybes
s。
当然,您的原始函数只需要传递参数即可:
getFoos ma mb mc = getFoosArr [ma, mb, mc]
如果您具有异构类型,但是无论如何都希望将其全部转换为String
,则很容易;使getFoosArr
取[Maybe String]
,并在进一步传递之前转换Just
s:
getFoosHet ma mb mc = getFoosArr
[ fmap showA ma
, fmap showB mb
, fmap showC mc
]
我假设showA :: A -> String
,ma :: Just A
。
1 我已经将\a b -> fmap (a,) b
简化为\a -> fmap (a,)
。也可以将其写为fmap . (,)
,但我个人认为它的可读性较差。