Merge two lists with alternative elements in Haskell
我是新的Haskell,并尝试练习自己的Haskell技能。
我想实现一个合并两个列表的功能,以便每个列表中的项都是可替换的。
1 2 | ["a","b","c"] ["1","2","3"] |
合并后。
1 | ["a","1","b","2","c","3"] |
这是我的Haskell代码
1 2 3 4 5 |
只要两个列表的长度相同,代码就起作用。
但是我想对两个列表的长度进行一些错误检查。
如果两个列表的长度不同,那么我想报告一个错误。
1 2 3 |
如何完成其??他部分?
不建议使用
1 2 3 4 5 6 7 | mergeList :: [a] -> [a] -> Maybe [a] mergeList [] [] = Just [] mergeList (x:xs) (y:ys) = case mergeList xs ys of Just merged -> Just (x:y:merged) Nothing -> Nothing mergeList _ _ = Nothing |
有更多简洁的方法可以编写此代码,但是我待在底层。
现在,
如果列表中的一个完全为空,则在模式匹配中引发错误。
所以你会有
1 2 3 | mergeList (x: xs) (y: ys) = x: y: mergeList xs ys mergeList [] [] = [] mergeList _ _ = error"your error" -- falling through to this pattern means that exactly one of the lists is empty |
检查两个列表的长度是否相等有点多余,因为'length'具有O(n)复杂度,这意味着您将两次遍历列表(在相等长度的情况下)。
正如luqui正确指出的那样,存在更多使用Maybe类型解决问题的优雅方法。当您了解函子(也许是Functor类的实例)时,您可以这样写:
1 2 3 4 5 |
最简单的方法可能只是预先进行检查,然后将主要工作路由到辅助功能:
1 2 3 4 5 6 7 8 9 |
检查在主函数中完成,并且如果列表大小相同,则将它们交给执行主处理的内部函数。请注意
自从我写Haskell以来已经有一段时间了,因此对于任何语法问题,我深表歉意。
您还可以通过将签名更改为以下内容来概括该功能:
1 | mergeList::[a]->[a]->[a] |
由于您没有在函数中执行任何特定于Strings的操作。
您可以使用的其他功能可能是这样的:
示例:
1 2 3 4 |
或带有foldr的elliptic00解决方案,避免使用
luqui指出我们希望在Haskell中保持安全,避免使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import Data.Bifunctor import Data.Bifunctor.Fix import Data.Bifunctor.Tannen data ListF l a = NilF | ConsF a l instance Bifunctor ListF where bimap _ _ NilF = NilF bimap f g (ConsF a l) = ConsF (f a) (g l) {-instance Bifoldable ListF where ... instance Bitraversable ListF where ... -} type List = Fix ListF |
但是我们可以添加错误处理:
1 |
一个
但是,这种合成方法最终变得非常冗长,令人困惑并且效率低下。实际上,更好的方法是使用完全自定义的列表类型:
1 | data EList' e a = Error e | Nil | Cons a (EList' e a) |