-2

I got this code to make a transposed matrix, but it doesn't work 100% fine.

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

I am trying to figure it out, but i really don't know which case is missing.

Redu
  • 25,060
  • 6
  • 56
  • 76
tbotl
  • 23
  • 6
  • 8
    Please provide a more useful question title. – deceze Nov 28 '18 at 15:15
  • this approach is *very* wrong. transposing a matrix should only be about manipulating the elements positionally, without regard to their values, but `delete` works with the elements' values. – Will Ness Nov 28 '18 at 15:47
  • 2
    the answer you're looking for is: there's a missing comma in `[[1,2,3],[0,4,5],[0,06]]`. – Will Ness Nov 28 '18 at 15:48
  • @WillNess yes, my mistake, i already put a comma but still the same mistake. Someone posted here another way to do this transpose function – tbotl Nov 28 '18 at 17:58
  • @deceze sorry, first time here – tbotl Nov 28 '18 at 17:59

2 Answers2

4

To discover which cases you are missing, you should turn on warnings using the -Wall flag, as shown in the GHCi session below.

> :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’

So, the case you are missing is:

primelem ([]:t) = ...
chi
  • 111,837
  • 3
  • 133
  • 218
  • i still couldn't solve it, because in a matrix all the lines have numbers so it can't be possible that the first line is an empty list – tbotl Nov 28 '18 at 15:30
  • 2
    @tbotl no, the error message you got says that you did hit that case at run time. – Will Ness Nov 28 '18 at 15:45
  • @tbotl Initially, yes, that's true. But your last row has only two columns, while other rows have three (since you forgot a comma, apparently). So, after two columns are removed, we get to a "matrix" which has two nonempty rows, and a last empty row, triggering the error. – chi Nov 28 '18 at 16:36
1

You're over-thinking this. A list of empty lists is its own transpose.

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

Otherwise, take the first element of each list as the first row of the transpose, and transpose the remaining matrix as the rest of the transpose.

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

This function is effectively total, failing only on those lists-of-lists that aren't actually matrices. The fact that it fails late on non-matrix values is a bit of a wart:

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

If you want to handle invalid matrices a little more cleanly, return a Maybe (Mat a) instead.

transpose :: Mat a -> Maybe (Mat a)
transpose m | all null m = Just []
            | any null m = Nothing
            | otherwise  = ((map head m):) <$> transpose (map tail m)
chepner
  • 497,756
  • 71
  • 530
  • 681
  • 1
    For what it is worth, the `transpose` function form the library does work on "jagged matrices", skipping over missing entries. E.g. `transpose [[1,2],[3],[4,5]] = [[1,3,4],[2,5]]`. On whether that feature is useful or harmful, I'm not sure. – chi Nov 28 '18 at 16:40
  • I'd say that's the subtle difference between `transpose :: [[a]] -> [[a]]` and `transpose :: Mat a -> Mat a`; the latter should strive to preserve the intention that `Mat a` really is a valid matrix type, and not expose the leaky abstraction provided by the `type` alias. – chepner Nov 28 '18 at 21:28