Я пытаюсь узнать у меня Haskell, и я решил практиковать, написав простую функцию для инвертирования матриц 3x3. Это должно быть легко, но я ничего не попытаюсь скомпилировать.Функция охранников и синтаксис «где» в Haskell
Вот мой код:
matInv3x3 :: [[Double]] -> [[Double]]
matInv3x3 m
| length m /= 3 = error "wrong number of rows"
| length (m !! 0) /= 3 = error "wrong number of elements in row 0"
| length (m !! 1) /= 3 = error "wrong number of elements in row 1"
| length (m !! 2) /= 3 = error "wrong number of elements in row 2"
| det == 0 = error "zero determinant"
| otherwise = mInv
where a = m !! 0 !! 0
b = m !! 0 !! 1
c = m !! 0 !! 2
d = m !! 1 !! 0
e = m !! 1 !! 1
f = m !! 1 !! 2
g = m !! 2 !! 0
h = m !! 2 !! 1
i = m !! 2 !! 2
det = a*(e*i - f*h) - b*(i*d - f*g) + c*(d*h - e*g)
A = (e*i - f*h)/det
B = -(d*i - f*g)/det
C = (d*h - e*g)/det
D = -(b*i - c*h)/det
E = (a*i - c*g)/det
F = -(a*h - b*g)/det
G = (b*f - c*e)/det
H = -(a*f - c*d)/det
I = (a*e - b*d)/det
mInv = [[A,B,C],[D,E,F],[G,H,I]]
Я пытаюсь защититься от всего, что может пойти не так: плохие размеры списка, и нулевой определителя. Я смоделировал его после примеров в книге «Learn You A ...». Я пытаюсь полагаться на ленивую оценку, если матрица имеет нулевой детерминант.
GHCi не будет скомпилировать его, ссылаясь на ошибку синтаксического анализа для '=' в строке 10 (где b задано). Я уверен, что есть простейшая, фундаментальная вещь, которую мне не хватает. Может кто-нибудь указать, что я сделал не так?
UPDATE:
Я реализовал исправления, предложенные в комментариях, а также исправил выгружена индексы ошибку, которую я сделал (не заметил его раньше, так как код не скомпилируется). Вот фиксированный код, который переворачивает 3x3 матриц правильно:
matInv3x3 :: [[Double]] -> [[Double]]
matInv3x3 m
| length m /= 3 = error "wrong number of rows"
| length (m !! 0) /= 3 = error "wrong number of elements in row 0"
| length (m !! 1) /= 3 = error "wrong number of elements in row 1"
| length (m !! 2) /= 3 = error "wrong number of elements in row 2"
| abs det < 1.0e-15 = error "zero or near-zero determinant"
| otherwise = mInv
where [[a,d,g],[b,e,h],[c,f,i]] = m
det = a*(e*i - f*h) - b*(i*d - f*g) + c*(d*h - e*g)
a' = (e*i - f*h)/det
b' = -(d*i - f*g)/det
c' = (d*h - e*g)/det
d' = -(b*i - c*h)/det
e' = (a*i - c*g)/det
f' = -(a*h - b*g)/det
g' = (b*f - c*e)/det
h' = -(a*f - c*d)/det
i' = (a*e - b*d)/det
mInv = [[a',b',c'],[d',e',f'],[g',h',i']]
Нет ошибки на линии, которую вы упомянули при компиляции, возможно, ваш отступ в вашем редакторе отличается от этого? С другой стороны, вы не можете указывать имена переменных, начинающиеся с заглавных букв - 'A',' B' .. 'I' - все недопустимы. Вы можете сделать '_A'. – user2407038
Haskell чувствителен к белому пространству. Предложение 'where' выглядит подозрительным для меня, я бы поставил его, по крайней мере, на три пространства. – crockeea
У меня была «таблетка» вместо четырех пробелов, которая невидимо прикручивала ее. Я исправил это, а также использовал _A, как вы предложили. Теперь функция работает так, как ожидалось. Спасибо за совет! – user2790167