避免不完整的模式匹配

Cli*_*ton 8 refactoring haskell list pattern-matching

请考虑以下代码:

data A
data B

f :: A -> B
f = undefined

data T = TA A | TB B
data ListT = ListTA [A] | ListTB [B]

g :: [T] -> ListT
g l = 
  let
    f' :: T -> B
    f' (TA x) = f x
    f' (TB x) = x
    isA :: T -> Bool
    isA TA{} = True
    isA TB{} = False
  in
    case (all isA l) of
      True -> ListTA (map (\(TA x) -> x) l)
      False -> ListTB (map f' l)

main = pure ()
Run Code Online (Sandbox Code Playgroud)

这背后的想法是我有一个As或Bs混合在一起的列表.我可以转换A -> B但不是相反.根据这个列表,我想要制作一个As列表或s列表B,前者如果我的所有原始列表元素都是As,后者如果至少有一个是a B.

上面的代码编译(我猜测会起作用)但是不完整的模式匹配map (\(TA x) -> x) l让我有点不舒服.这种不完全匹配只是我在这里做的必要吗?另外,我是否重新发明轮子,有什么能够概括我在这里所做的事情吗?

Cli*_*ton 1

在获得其他答案的帮助后,我将回答我自己的问题,以造福未来的观众。我相信最简洁的函数如下g(并注意到我已经概括为Traversable而不仅仅是列表)。

data ListT t = ListTA (t A) | ListTB (t B)

g :: (Traversable t) => t T -> ListT t
g l = 
  let
    f2B :: T -> B
    f2B (TA x) = f x
    f2B (TB x) = x
    f2A :: T -> Maybe A
    f2A (TA x) = Just x
    f2A (TB x) = Nothing
  in
    maybe (ListTB (fmap f2B l)) ListTA (traverse f2A l)

main = pure ()
Run Code Online (Sandbox Code Playgroud)

在列表上,这应该只占用与前导 s 的数量成比例的空间A,我认为这是最小的。