Все еще путают, как работает подпись типа с несколькими стрелками - PullRequest
0 голосов
/ 12 июня 2018

Я проверил сообщение раньше и, кажется, понимаю.Я знаю,

f :: a -> b -> c 

- это форма карри

g :: (a, b) -> c

Но поскольку сигнатура типа становится длиннее, чем 2 стрелки, я снова чувствую себя сбитым с толку.

myscanr :: (a -> b -> b) -> b -> [a] -> [b]
myscanr op z [] = [z]
myscanr op z (x:xs) = op x (head qs) : qs
  where
    qs = myscanr op z xs

Являются ли (a -> b -> b) и [b] входом и выходом?Каковы остальные в середине тогда?

Ответы [ 3 ]

0 голосов
/ 12 июня 2018

Чтение сигнатур типа в виде преобразования ... -> to, где аргументы - «покой в ​​середине».

например.myscanr :: (a -> b -> b) -> b -> [a] -> [b] «берет» функцию (a -> b -> b), a b, список из [a] и возвращает вам список из b [b]

0 голосов
/ 12 июня 2018

Что ж, концептуально, функция в Haskell всегда имеет ровно один параметр.Действительно, на самом деле подпись:

myscanr :: (a ->  b -> b ) ->  b ->  [a] -> [b]

- это сокращение от:

myscanr :: (a -> (b -> b)) -> (b -> ([a] -> [b]))

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

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

# python

def add(x):
    def addx(y):
        return x + y
    return addx

Итак, здесь у нас есть функция add.Мы можем вызвать его с одним параметром x.Если мы сделаем это, например, с x=4, то он вернет другую функцию (где x ограничен).Только если мы затем вызовем эту функцию с параметром (например, y=3), мы получим результат, например:

>>> add(4)
<function add.<locals>.addx at 0x7f1c519e7b70>
>>> add(4)(3)
7

Хорошо, в Haskell эта модель является стандартной: каждая функция принимаеттолько один параметр.Но так как это так, синтаксис может быть улучшен.Вместо того, чтобы писать ((myscanr((+)))(0))([1, 4, 2, 5]), мы можем написать myscanr (+) 0 [1, 4, 2, 5], и Haskell автоматически интерпретирует это как вызов функции с myscanr в качестве функции и (+) в качестве параметра, другой вызов функции с функцией как результат предыдущеговызов и 0 в качестве параметра, а затем другой вызов функции с функцией как результат предыдущего вызова с [1, 4, 2, 5] в качестве параметра.

Так как синтаксически это выглядит немного, как если бы мы сделали вызов с Три параметров, можно сказать, что (a -> b -> b), b и [a] являются типами " три параметра ".Но, строго говоря, это неправильно.

0 голосов
/ 12 июня 2018

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

В этом примере ваши типы параметров: (a -> b -> b), b и [a]: функция принимает a и b ивозвращая b, b и список a с.

Тип возврата - последний тип в подписи [b]: список b с.

...