我无法搞清楚这个功能:
定义一个带有对列表的函数
maybeA :: [(String, a)] -> Maybe (String, a, a)
。如果输入列表有两对(a1, b1), (a2, b2)
,使得a1 = a2,则该函数返回包含a1和b1,b2的元组。否则它返回Nothing。示例:maybeA [("a", 1), ("b", 2), ("b", 3)]
将返回Just ("b", 2, 3)
。
任何提示?
答案 0 :(得分:3)
这是一个“组合方法” - 将问题分解为简单的小步骤,然后使用函数组合逐个应用这些步骤:
import Data.List (sort, groupBy)
import Data.Maybe (listToMaybe)
import Data.Function (on)
maybeA = fmap formatAnswer . listToMaybe . dropWhile (null . drop 1) .
groupBy ((==) `on` fst) . sort
where
formatAnswer ((a, b1):(_, b2):_) = (a, b1, b2)
一些注意事项:
fmap
将函数应用于Maybe
内的值(如果存在)。 (fmap
也可以在许多其他类型上以类似的方式工作。)(==)
`` fst
`测试两个元组的第一个元素是否相等。sort
比较元组中的两个元素,但它使用字典顺序。所以它可以在这里工作,但它有时会改变b1
和b2
的顺序。如果这对你来说是个问题,
请改用sortBy (comparing fst)
。 sortBy
位于Data.List
模块中,comparing
位于Data.Function
模块中。答案 1 :(得分:1)
如果您只是在寻找前两次出现的情况,其中两对具有相同的前两个元素,那么以下定义将起作用:
maybeA :: [(String, a)] -> Maybe (String, a, a)
maybeA = maybeA' []
where
maybeA' _ [] = Nothing
maybeA' as ((x,y):xys) =
case lookup x as of
Just y' -> Just (x,y,y')
Nothing -> maybeA' ((x,y):as) xys
注意,如果您传递一个包含(a1, b1)
,(a2, b2)
和(a3, b3)
的列表,其中a1
== a2
和a2
= = a3
,它只返回Just (a1, b1,b2)
而不是Just (a1, b1,b2,b3)
(甚至不是同一类型)。
设计一个执行此操作的函数作为练习: - )