我有一些代码在进行显式递归,最重要的是它在不需要的时候调用相同的函数两次。我想我可以修复后者,但需要帮助前者。
yesodIdentifier :: Text -> [LDAPEntry] -> Text
yesodIdentifier name ((LDAPEntry _ attributes):_) =
let (Just eMail) = L.lookup "proxyAddresses" attributes
partedEmail = L.map (S.splitOn "@") eMail -- now we have
-- [["garbage:name","domain"]]
in yesodIdentifier' name partedEmail -- the secondary function is the problem
where yesodIdentifier' :: Text -> [[String]] -> Text
yesodIdentifier' nameToMatch ((name:[domain]):rest) =
if ((unpack nameToMatch) == (sanitized name))
then (pack (sanitized name)) `append`
(pack "@") `append`
(pack domain)
else yesodIdentifier' nameToMatch rest
where sanitized :: String -> String
sanitized dirty =
let (garbage:[cleanedName]) = S.splitOn ":" dirty
in cleanedName
yesodIdentifier' name _ = pack "empty identifier"
我想要做的是从LDAPEntry获取(String,[String]),并将其减少到与给定名称匹配的电子邮件地址。
您可以看到递归的位置。如果我能解决这个问题,我就不必担心yesodIdentifier' name _ = pack "empty identifier"
,因为在用户不在LDAP数据库中的情况下,不会调用此代码。我只是把它放在那里完成。
我认为这可以更好地表达为折叠,但我无法在脑海中正确表达。有什么想法吗?
答案 0 :(得分:2)
这可以表示为过滤器。这不是一个折叠,因为,如果你进行递归,你会在休息时递归并丢弃之前的条目。您仍然需要处理空列表:
yesodI nameToMatch list = let result = filter (match(unpack nameToMatch)) list match s1 (s2:[domain]) = s1 == s2 in case result of [] -> "empty identifier" res -> repack (head res) repack arg@(name:[domain]) = (pack (sanitized name)) `append` (pack "@") `append` (pack domain)
答案 1 :(得分:1)
从ja回答,改写使用find:
yesodI name l = intercalate "@" <$> (find ((name ==) . head) $ filter (not . null) l)
更易阅读的版本
yesodI name list = repack <$> find matchName list'
where list' = filter (not . null) list
repack = intercalate "@"
matchName = (name ==) . head
答案 2 :(得分:0)
您可以先将电子邮件地址清理为(name, domain)
对,然后使用find
找到匹配名称的第一个电子邮件地址,然后maybe
确定如果您执行了找不到匹配:
yesodIdentifier :: Text -> [LDAPEntry] -> Text
yesodIdentifier name ((LDAPEntry _ attributes):_) =
let (Just eMail) = L.lookup "proxyAddresses" attributes
name' = T.unpack name
sanitizedEmail = concatMap sanitize eMail -- now we have [("name","domain")]
empty = "empty identifier"
nonEmpty (name, domain) = concat [name, "@", domain]
sanitize s = do
(dirtyName:[domain]) <- [S.splitOn "@" s]
(garbage:[cleanedName]) <- [S.splitOn ":" dirtyName]
return (cleanedName, domain)
in T.pack . maybe empty nonEmpty . L.find ((name' ==).fst) $ sanitizedEmail
这是完全未经测试的,因为我没有您提供的所有类型...我希望santize
中的List Monad
会丢弃无法分解的电子邮件地址{{ 1}}。