Есть ли конкретный тип для математических функций в Haskell? - PullRequest
0 голосов
/ 16 января 2019

Я хочу написать функцию, которая принимает математическую функцию (/, x, +, -), число для начала и список чисел. Затем он должен вернуть список.

Первый элемент - это начальный номер, второй - значение начального номера плюс / минус / раз /, деленное на первый номер заданного списка. Третий элемент - это результат предыдущего результата плюс / минус / раз /, разделенный на второй результат данного списка и т. Д.

Я получил все для работы, если я скажу коду, какую функцию использовать, но если я хочу позволить пользователю вводить математическую функцию, которую он хочет, возникают проблемы с типами. Попытка: t (/), например, выдает Fractional a => a -> a -> a, но если вы положите это в начало ваших типов, это не удастся.

Существует ли определенный тип для различения этих функций (/, x, +, -)? Или есть другой способ успешно написать эту функцию?

prefix :: (Fractional a, Num a) => a -> a -> a -> a -> [a] -> [a]

prefix (f) a b = [a] ++ prefix' (f) a b


prefix' :: (Fractional a, Num a) => a -> a -> a -> a -> [a] -> [a]

prefix' (z) x [] = []

prefix' (z) x y = [x z (head y)] ++ prefix' (z) (head (prefix' (z) x y)) (tail y)

Правильное решение будет примерно таким:

prefix (-) 0 [1..5]

[0,-1,-3,-6,-10,-15]

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Если вы хотите ограничиться этими четырьмя операциями, просто определите тип самостоятельно:

data ArithOp = Plus | Minus | Times | Div

as_fun Plus = (+)
as_fun Minus = (-)
as_fun Times = (*)
as_fun Div = (/)
0 голосов
/ 16 января 2019

Существует ли определенный тип для различения этих функций (/, *, +, -)?

Я не вижу причин длясделай это.Почему \x y -> x+y считается "лучше", чем \x y -> x + y + 1.Конечно, добавление двух чисел - это то, что большинство посчитает более «чистым».Но странно ограничивать себя определенным набором функций.Также возможно, что для некоторой функции \x y -> f x y - 1 "случается" равным (+), за исключением того, что компилятор не может этого определить.

Проверка типа гарантирует, что нельзя передавать функции, которыеработать с числами, учитывая, что список содержит строки и т. д. Но намеренное ограничение этого в дальнейшем не очень полезно.Почему вы не позволяете программистам использовать вашу функцию для различных целей?

Или есть другой способ успешно написать эту функцию?

То, что вы здесь описываете, это функция scanl :: (b -> a -> b) -> b -> [a] -> [b].Если мы позвоним scanl с scanl f z [x1, x2, ..., xn], то получим список [z, f z x1, f (f z x1) x2, ...].scanl можно определить как:

scanl :: (b -> a -> b) -> b -> [a] -> [b]
scanl f = go
    where go z [] = [z]
          go z (x:xs) = z : go (f z x) xs

Таким образом, мы сначала излучаем аккумулятор (который начинается с начального значения), а затем "обновляем" аккумулятор до f z x с помощьюz старый аккумулятор и x глава списка, и рекурс в конце списка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...