тип подписи Haskell

cow :: (Eq a) => a -> a -> [a] -> Bool
cow x y z = x && y `elem` z

 foo ::
 foo x y z = x `elem` y && y `elem` z

 bar::
 bar x y = case y of
    Nothing -> x
    Just z  -> x + z

Я не знаю, какой должна быть подпись типа.


person Jayyyyyy    schedule 09.10.2019    source источник
comment
Подсказка: найдите подписи elem, (+) и (&&).   -  person Willem Van Onsem    schedule 09.10.2019
comment
может быть elem используется, чтобы узнать, находится ли x&&y в списке Z? Я не очень уверен, поэтому я использовал Bool.   -  person Jayyyyyy    schedule 09.10.2019
comment
вам не нужно знать, что делает функция, чтобы определить типы. Сигнатуры можно вывести, просто взглянув на сигнатуры используемых вами функций.   -  person Willem Van Onsem    schedule 09.10.2019
comment
cow тоже неправильно.   -  person amalloy    schedule 09.10.2019


Ответы (1)


Для того, чтобы определить тип подписи. Вам не нужно знать, что делает функция. Вы можете использовать сигнатуры типов функций, которые вы используете, и делать выводы об этом.

Поскольку сигнатура типа вашей функции cow не совсем верна, мы покажем, как получить сигнатуру типа функции cow, а затем оставим две другие в качестве упражнений.

Мы видим, что cow здесь имеет три параметра: x, y и z. На данный момент мы мало что знаем о x, y и z. Поэтому мы назначим переменную другого типа для этих переменных. Итак, x :: a, y :: b и z :: c.

Далее мы можем начать выводить типы. Определение функции cow:

cow x y z = x && y `elem` z

можно записать в более каноническом формате как:

cow x y z = (&&) x (elem y z)

Таким образом, мы видим, что здесь используются две функции: (&&) :: Bool -> Bool -> Bool и elem :: (Eq e, Foldable f) => e -> f e -> Bool, здесь мы используем e вместо f, чтобы избежать "конфликтов имен" с нашей уже определенной переменной типа a. Поскольку мы используем x в качестве аргумента функции (&&) :: Bool -> Bool -> Bool, мы знаем, что x должен иметь тип Bool, и, следовательно, a ~ Bool (a имеет тот же тип, что и Bool). Кроме того, мы таким образом знаем, что (&&) x :: Bool -> Bool.

Далее мы видим, что вызываем elem :: (Eq e, Foldable f) => e -> f e -> Bool. Таким образом, это означает, что y, который является первым параметром, примененным к elem, имеет тип e и, следовательно, b ~ e.

Кроме того, это означает, что elem x имеет тип (Eq e, Foldable f) => f e -> Bool, и мы применяем эту функцию к параметру z. Таким образом, это означает, что c ~ (Eq e, Foldable f) => f e и что тип elem y z равен Bool.

Поскольку тип elem y z равен Bool, это соответствует функции (&&) x, и, таким образом, тип (&&) x (elem y z) равен Bool.

Таким образом, мы пришли к выводу, что:

x :: Bool
y :: e
z :: f e

с ограничениями типа Eq e и Foldable f. Таким образом, это означает, что cow имеет функцию:

cow :: (Eq e, Foldable f) => Bool -> e -> f e -> Bool
cow x y z = x && y `elem` z
person Willem Van Onsem    schedule 09.10.2019
comment
И, конечно, Foldable f может быть специализировано для [], давая Bool -> a -> [a] -> Bool - person Jon Purdy; 09.10.2019
comment
@JonPurdy: да, правильно. Проблема больше связана с x в предлагаемой подписи в вопросе. - person Willem Van Onsem; 09.10.2019