在Haskell中,我需要执行一个函数,其类型声明如下:
split ::[Integer] -> Maybe ([Integer],[Integer])
让它如下工作:
split [1,2,3,4,5,15] = Just ([1,2,3,4,5],[15])
因为,1 + 2 + 3 + 4 + 5 = 15
split [1,3,3,4,3] = Just ([1,3,3],[4,3])
因为,1 + 3 + 3 = 7 = 4 + 3
split [1,5,7,8,0] = Nothing
我试过这个,但它不起作用:
split :: [Integer] -> ([Integer], [Integer])
split xs = (ys, zs)
where
ys <- subsequences xs, ys isInfixOf xs, sum ys == sum zs
zs == xs \\ ys
确定正整数列表xs是否可以用相同的和分成两部分(不重新排列其元素)。如果可能,其值是由两部分组成的对。如果不是,则其值为Nothing。 我该怎么办?
答案 0 :(得分:3)
不是一个完整的答案,因为这是一个学习练习并且您需要提示,但如果您想使用subsequences
中的Data.List
,则可以删除您正在检查的子序列的每个元素带有\\
的原始列表,以获得差异,并比较总和。你是在正确的轨道上,但你需要找到有效的第一个子序列并返回Just (ys, zs)
,否则Nothing
。
您可以将某个给定子序列的测试作为谓词,并使用find
进行搜索。
答案 1 :(得分:1)
您还可以创建一个函数,该函数提供列表的所有可能拆分:
splits :: [a] -> [([a], [a])]
splits xs = zipWith splitAt [1..(length xs)-1] $ repeat xs
其工作原理如下:
*Main> splits [1,2,3,4,5,15]
[([1],[2,3,4,5,15]),([1,2],[3,4,5,15]),([1,2,3],[4,5,15]),([1,2,3,4],[5,15]),([1,2,3,4,5],[15])]
然后您可以使用Data.List
中的find
来查找具有相等总和的第一对拆分列表:
import Data.List
splitSum :: [Integer] -> Maybe ([Integer], [Integer])
splitSum xs = find (\(x, y) -> sum x == sum y) $ splits xs
符合预期:
*Main> splitSum [1,2,3,4,5,15]
Just ([1,2,3,4,5],[15])
由于find
返回Maybe a
,因此类型会自动匹配。