如何为不同类型的输入定义防护措施?

时间:2018-03-22 09:03:04

标签: haskell

我正在尝试将输入列表转换为回文结构。例如:

Input: [1,2,3]
Output: [1,2,3,3,2,1]

基本上我需要添加一个反向列表。我的问题在于:

palindrize::[a]->[a]
palindrize list | null list = []
palindrize (x:xs)=(x:xs)++revert(x:xs) where
                  revert list | null list =[] 
                  revert (x:xs)= (revert xs):(x:[])   ---Here 

当只有一个元素从中创建一个列表时(应用(myelement:[])),如何创建一个保护或条件?我需要以某种方式说:revert可以获取列表或元素,如果它是一个元素应用(element:[])

2 个答案:

答案 0 :(得分:4)

我认为你把事情弄得太复杂了。首先,Haskell已经有一个reverse :: [a] -> [a]来反转列表,所以我们可以做到:

palindrize :: [a] -> [a]
palindrize l = l ++ reverse l

此外,这里不需要使用防护装置。我们可以执行模式匹配:这样更安全,因为编译器可以保证我们所有模式都被覆盖。所以我们可以这样写:

revert :: [a] -> [a]
revert [] = []
revert (x:xs) = (revert xs):(x:[])  -- error!

但这会导致类型错误。实际上,(:)构造函数的类型为(:) :: a -> [a] -> [a],但revert xs将生成类型[a]。在像这样的情况下,最好使用 accumulator :我们使用空列表初始化的参数,然后每个递归调用更新并在递归过程结束时返回。例如:

revert :: [a] -> [a]
revert = go []
    where go xs [] = xs
          go xs (x:ys) = go (x:xs) ys

答案 1 :(得分:1)

首先,你不能写list : element,也不能list : (element : []),因为类型不匹配::左侧的任何内容都必须与列表位于右侧。

但是,您可以使用++附加两个列表,例如list ++ (element : [])list ++ [element]

其次,要对单个元素列表进行模式匹配,可以使用

foo [] = ... -- empty list case
foo [x] = ... -- single element list case
foo (x1:x2:rest) = ... -- two elements or more case

如果您愿意,也可以编写单个元素大小写foo (x:[]) = ...

请注意,foo [] = ...相当于foo list | null list = ...,但更简单。如果可能的话,忘记警卫:它们只应在模式匹配不够时使用。