Подтвердить что ты не робот

Что означает → означает в F #?

Я пытался зайти в F # на некоторое время, но я все время откладываю. Почему?

Потому что независимо от того, какой ресурс новичков я пытаюсь посмотреть, я вижу очень простые примеры, которые начинают использовать оператор ->.

Однако нигде я не нашел, что дает четкое простое объяснение того, что означает этот оператор. Это, как если бы это было так очевидно, что это не нуждается в объяснении даже для того, чтобы закончить новичков.

Поэтому я должен быть действительно плотным или, может быть, почти три десятилетия предыдущего опыта удерживают меня.

Может кто-нибудь, объясните это или укажите действительно доступный ресурс, который объясняет это?

4b9b3361

Ответ 1

'- > ' не является оператором. Он появляется в синтаксисе F # в ряде мест, и его значение зависит от того, как оно используется как часть более крупной конструкции.

Внутри типа '- > ' описывает типы функций, как описано выше. Например

let f : int -> int = ...

говорит, что 'f' - это функция, которая принимает int и возвращает int.

Внутри лямбда ( "вещь, которая начинается с" веселого "ключевого слова" ), '- > ' - это синтаксис, который отделяет аргументы от тела. Например

fun x y -> x + y + 1

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

Внутри конструкции "match" '- > ' - синтаксис, который отделяет шаблоны от кода, который должен выполняться, если шаблон сопоставляется. Например, в

match someList with
| [] -> 0
| h::t -> 1

материал слева от каждого '- > ' - это шаблоны, а материал справа - это то, что происходит, если шаблон слева был сопоставлен.

Трудность понимания может быть связана с ошибочным предположением, что '- > ' является "оператором" с одним значением. Аналогия может быть "." в С#, если вы никогда не видели какой-либо код раньше, и попытайтесь проанализировать ".". оператор, основанный на взгляде на "obj.Method" и "3.14" и "System.Collections", вы можете сильно запутаться, потому что символ имеет разные значения в разных контекстах. Однако, когда вы знаете достаточно языка для распознавания этих контекстов, все становится ясно.

Ответ 2

В основном это означает "карты". Прочтите это так или как "преобразуется" или что-то в этом роде.

Итак, из F # за 20 минут учебник,

> List.map (fun x -> x % 2 = 0) [1 .. 10];;
val it : bool list
= [false; true; false; true; false; true; false; true; false; true]

Код (fun я → i% 2 = 0) определяет анонимная функция, называемая лямбдой выражение, которое имеет параметр x и функция возвращает результат "x % 2 = 0", то есть, является ли x равно даже.

Ответ 3

Первый вопрос: знакомы ли вы с лямбда-выражениями на С#? Если так, то → в F # совпадает с = > в С# (я думаю, вы читаете "идет" ).

Оператор → также может быть найден в контексте сопоставления шаблонов

match x with
| 1 -> dosomething
| _ -> dosomethingelse

Я не уверен, что это также выражение лямбда или что-то еще, но я думаю, что "идет" все еще сохраняется.

Возможно, вы действительно имеете в виду, что это криптографические ответы парсера F #:

> let add a b = a + b
val add: int -> int -> int

Это означает (как объясняет большинство примеров), что add - это 'val', который принимает два int и возвращает int. Для меня это было совершенно непрозрачно для начала. Я имею в виду, откуда я знаю, что add - это не val, который принимает один int и возвращает два ints?

Ну, дело в том, что в некотором смысле это так. Если я даю добавить только один int, я возвращаю (int → int):

> let inc = add 1
val inc: int -> int

Это (currying) - одна из вещей, которая делает F # такой сексуальной, для меня.

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

Ответ 4

(a → b) означает "функция от a до b". В аннотации типа он обозначает тип функции. Например, f: (int → String) означает, что f относится к функции, которая принимает целое число и возвращает строку. Он также используется в качестве контрструктора таких значений, как в

val f : (int -> int) = fun n -> n * 2

который создает значение, которое является функцией от некоторого числа n до того же числа, умноженного на два.

Ответ 5

От Microsoft:

Типы функций - это типы, первоклассные значения функций и написанный int → int. Они подобны к типам делегатов .NET, за исключением того, что они не указаны имена. Все функции F # идентификаторы могут использоваться как первоклассные значения функций и анонимные значения функции могут быть созданы с использованием формулу (fun... → ...).

Ответ 6

Здесь уже много замечательных ответов, я просто хочу добавить к разговору еще один способ подумать об этом.

'- > ' означает функцию.

'a → ' b - это функция, которая берет 'a и возвращает a' b

('a *' b) → ('c *' d) - это функция, которая берет набор типа ('a,' b) и возвращает набор ('c,' d). Например, int/string возвращает float/ char.

Где он интересен, в каскадном случае "a → " b → "c. Это функция, которая принимает 'a и возвращает функцию (' b → 'c), или функцию, которая берет' b → 'c.

Итак, если вы пишете:  пусть f x y z =()

Тип будет f: 'a → ' b → 'c → unit, поэтому, если вы применили только первый параметр, результатом будет точечная функция b → ' c → '.

Ответ 7

В контексте определения функции он похож на => на выражение лямбда в С# 3.0.

F#: let f = fun x -> x*x
C#: Func<int, int> f = x => x * x;

-> в F # также используется в сопоставлении с образцом, где это означает: если выражение соответствует части между | и ->, то то, что появляется после ->, должно быть возвращено в качестве результата:

let isOne x = match x with
 | 1 -> true
 | _ -> false

Ответ 8

Много замечательных ответов на эти вопросы, спасибо людям. Я хотел бы добавить редактируемый ответ, который объединяет вещи.

Для тех, кто знаком с пониманием С# → , то же самое, что и выражение lamba - это хороший первый шаг. Это использование: -

fun x y -> x + y + 1

Можно понимать как эквивалент: -

(x, y) => x + y + 1;

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

Следовательно, когда описанное выше описано так: -

Int -> Int -> Int

Это действительно помогло узнать, что → является правильным ассоциативным, поэтому можно рассмотреть выше: -

Int -> (Int -> Int)

Ага! У нас есть функция, которая принимает Int и возвращает (Int → Int) (каррическая функция?).

Объяснение, что → может также отображаться как часть определения типа, также помогло. (Int → Int) - это тип любой функции, которая принимает Int и возвращает Int.

Также полезно, что → появляется в другом синтаксисе, таком как совпадение, но там он не имеет того же значения? Это верно? Я не уверен, что это так. Я подозреваю, что он имеет то же значение, но у меня нет словарного запаса, чтобы выразить это.

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

Ответ 9

Хорошая вещь о таких языках, как Haskell (она очень похожа на F #, но я не знаю точного синтаксиса - это должно помочь вам понять → , хотя) заключается в том, что вы можете применять только части аргумента, для создания карриных функций:

adder n x y = n + x + y

Другими словами: "Дайте мне три вещи, и я добавлю их вместе". Когда вы бросаете в него числа, компилятор выводит типы n x и y. Скажем, вы пишете

adder 1 2 3

Тип 1, 2 и 3 - Int. Поэтому:

adder :: Int -> Int -> Int -> Int

То есть, дайте мне три целых числа, и я стану целым числом, в конце концов, или тем же, что сказать:

five :: Int
five = 5

Но, здесь хорошая часть! Попробуйте следующее:

add5 = adder 5

Как вы помните, сумматор принимает int, int, int и возвращает вам int. Однако это не вся правда, как вы вскоре увидите. Фактически, add5 будет иметь этот тип:

add5 :: Int -> Int -> Int

Это будет как будто вы "очистили" целые числа (самые левые) и приклеили их непосредственно к функции. Заглядывая ближе к сигнатуре функции, заметим, что → являются право-ассоциативными, т.е.

addder :: Int -> (Int -> (Int -> Int))

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

add5andtwomore :: Int -> (Int -> Int)
add5andtwomore = adder 5

Теперь вы можете использовать add5andtwomore вместо "сумматор 5". Таким образом, вы можете применить другое целое число, чтобы получить (скажем) "add5and7andonemore":

add5and7andonemore :: Int -> Int
add5and7andonemore = adder 5 7

Как вы видите, add5and7andonemore хочет точно другой аргумент, и когда вы его дадите, он внезапно станет целым!

  > add5and7andonemore 9
 => ((add5andtwomore) 7) 9
 => ((adder 5) 7) 9)
<=> adder 5 7 9

Подставляя параметры в сумматор (n x y) для (5 7 9), получаем:

  > adder 5 7 9 = 5 + 7 + 9
 => 5 + 7 + 9
 => 21

На самом деле, плюс - это просто функция, которая принимает int и возвращает вам еще один int, поэтому выше это больше похоже:

  > 5 + 7 + 9
 => (+ 5 (+ 7 9))
 => (+ 5 16)
 => 21

Там вы идете!