Реализация Haskell закона косинусов

Я пытаюсь реализовать закон закона косинусов, и вот мой код:

cosC :: [a] -> a
cosC sides
   | length sides < 3          = 0
   | otherwise                 = (x ^ 2 + y ^ 2 - z ^ 2) / (2 * x * y)
   where x = head(tail(tail(sides)))
         y = head(tail(sides))
         z = head(sides)

Но я получаю две ошибки:

No instance for (Fractional a)
arising from a use of `/'
In the expression: (x ^ 2 + y ^ 2 - z ^ 2) / (2 * x * y)
In an equation for `cosC':
    cosC sides
      | length sides < 3 = 0
      | otherwise = (x ^ 2 + y ^ 2 - z ^ 2) / (2 * x * y)
      where
          x = head (tail (tail (sides)))
          y = head (tail (sides))
          z = head (sides)

а также

No instance for (Num a)
arising from the literal `2'
In the first argument of `(*)', namely `2'
In the first argument of `(*)', namely `2 * x'
In the second argument of `(/)', namely `(2 * x * y)'

Изменить: я исправил опечатку в законе косинусов выше. Спасибо Дэниелу Фишеру за указание на это.

2 ответа

Решение

Вы пытаетесь вычислить числовые результаты из общих типов aЭто не может работать. (Это все равно что пытаться построить мост не только для обычных дорожных транспортных средств, но и для обычных вещей, например, космических кораблей, небоскребов, скрепок и нейтронных звезд). Просто добавьте Floating ограничение к:

cosC :: Floating a => [a] -> a

и вы можете выполнять любые арифметические операции, необходимые для такого расчета. (Fractional на самом деле достаточно для этой функции, но вы не сможете рассчитать arccos результата потом).


Обратите внимание, что в Haskell гораздо лучший способ разложить списки, не связанный с вашей проблемой:

cosC (x:y:z:_) = (x^2 + y^2 - z^2) / (2*x*y)
cosC _ = 0

эквивалентно вашему определению. В любом случае, почему вы берете аргументы в виде списка? Это довольно странная вещь на Лиспе, в Хаскеле я бы предпочел

cosC :: Floating a => a -> a -> a -> a
cosC x y z = (x^2 + y^2 - z^2) / (2*x*y)

cosC :: Fractional a => [a] -> a

И вот как вы можете узнать (в ghci):

*Main> let fun [x, y, z] = (x * x + y * y + z * z) / (2 * x * y)
*Main> :type fun
fun :: Fractional a => [a] -> a
Другие вопросы по тегам