我该如何在Haskell中解决此问题?

时间:2018-11-28 15:13:26

标签: haskell

我得到了这段代码来制作转置矩阵,但是并不能100%正常工作。

type Mat a = [[a]]

transpose' :: Eq a => Mat a -> Mat a
transpose' [] = []
transpose' (h:t) = primelem (h:t):transpose' (eliminate' (h:t))

primelem :: Mat a -> [a]
primelem [] = []
primelem [[x]] = [x] 
primelem ((x:xs):t) = x : primelem t

eliminate' :: Eq a => Mat a -> Mat a
eliminate' [] = []
eliminate' (h:t) = (delete (head h) h):eliminate' t

*Main> transpose' [[1,2,3],[0,4,5],[0,06]]

[[1,0,0],[2,4,6],[3,5*** Exception:(..)Non-exhaustive patterns in function primelem

我正在设法弄清楚,但我真的不知道缺少哪种情况。

2 个答案:

答案 0 :(得分:5)

要发现丢失的情况,应使用-Wall标志打开警告,如下面的GHCi会话所示。

> :set -Wall
> type Mat a = [[a]]
> :{
| primelem :: Mat a -> [a]
| primelem [] = []
| primelem [[x]] = [x] 
| primelem ((x:xs):t) = x : primelem t
| :}

<interactive>:5:1: warning: [-Wincomplete-patterns]
    Pattern match(es) are non-exhaustive
    In an equation for ‘primelem’: Patterns not matched: ([]:_)

<interactive>:7:14: warning: [-Wunused-matches]
    Defined but not used: ‘xs’

因此,您失踪的情况是:

primelem ([]:t) = ...

答案 1 :(得分:2)

您对此太想了。空列表的列表是它自己的转置。

transpose m | all null m = []
            | any null m = error "Not a matrix"

否则,将每个列表的第一个元素作为转置的第一行,并将其余矩阵转置为转置的其余部分。

transpose m = map head m : transpose (map tail m)

此功能实际上是合计的,仅在那些实际上不是矩阵的列表中失败。它在非矩阵值上失败较晚的事实有点夸张:

> transpose [[1,2], [3]]
[[1,3]*** Exception: Not a matrix
CallStack (from HasCallStack):
  error, called at tmp.hs:3:28 in main:Main

如果您想更干净地处理无效矩阵,请返回Maybe (Mat a)

transpose :: Mat a -> Maybe (Mat a)
transpose m | all null m = Just []
            | any null m = Nothing
            | otherwise  = ((map head m):) <$> transpose (map tail m)