Вопрос Noob о параметре функции F #, где параметр является списком - PullRequest
0 голосов
/ 28 декабря 2018

Я пытаюсь поиграть с созданием функций в F #. На изображении ниже я пытаюсь создать функцию, которая берет список с плавающей точкой и суммирует значения в списке.Я не знаю, как передать список в качестве параметра функции, поэтому я попытался получить заголовок списка, но код не работает:

let sumlist l=
    printf "%f" l.Head

Тогда я вижу, что некоторые люди делают:

let sumlist l:float=
    match l with
    | [] -> 0.0
    | e::li -> e + sumlist li

Так ли l:float способ передачи списка функции?так как l:string будет списком строк?

Но я видел, что список l имеет функцию l.Head для возврата первого элемента в списке (так как мы не можем получить доступ к произвольным элементам всписок как массив) но

let sumlist l:float= 
    printfn "%f" l.Head 

выдает ошибку несоответствия типов.

Я также не понимаю предоставленный рекурсивный код, я не понимаю эту строку

| e::li -> e + sumlist li

Что такое ::?и Ли?

Спасибо за разъяснение этого для меня!

enter image description here

Ответы [ 2 ]

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

Синтаксические вопросы

Так что же такое l: float, как вы передаете список функции?

Нет.Большую часть времени компилятор может выяснить, что вы передаете список без аннотирования параметра как списка, но когда это не так, вы аннотируете:

l : 'a list // where 'a is generic type
// OR
l : float list // where type is specified as float

Что такое ::?и Li?

Когда шаблон соответствует списку, [] соответствует пустому списку, который здесь используется в качестве критерия окончания рекурсии.Другое совпадение отделяет голову (e) от остальной части списка, иначе говоря, tail (li).Если в списке только один элемент, то li оценивается как [].

Дополнительное примечание для вашего рекурсивного кода: вам не хватает ключевого слова рекурсии rec например.

let rec sumlist ...

Рекурсивная реализация функции

Самый простой способ - использовать функцию суммирования List , например.

[0.4; 0.5; 0.6] |> List.sum // Returns 1.5

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

let sumlist (values : float list) =
    let rec sum (acc : float) (remaining : float list) =
        match remaining with
        | [] -> acc
        | head :: tail -> sum (acc + head) tail
    sum 0. values

Что называется

[0.4; 0.5; 0.6] |> sumlist // Returns 1.5

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

0 голосов
/ 28 декабря 2018

Итак, ваш первый пример ничего не возвращает, и это потому, что вы вызываете printfn, которая печатает на консоль, а не возвращает ваши типы.Здесь e :: li представляет список, где e - голова, а li - остальная часть списка.:: здесь позволяет компилятору знать, что вы хотите деконструировать список.

//fully annotated
let s (l: float list) :float = 
    l.Head
//here the types can be inferred without any annotation
let rec sumlist l = 
    match l with
    | [] -> 0.0
    | e::li -> e + sumlist li

s [0.7]
//returns 0.7

sumlist [0.4;0.5;0.6]
//returns 1.5

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

Лично при запуске я настоятельно рекомендую всегда комментировать типы.(l : float list) или (l: list<float>) - это способ сказать, что мой ввод является списком с плавающей точкой, а :float в конце, как мы говорим, тип возвращаемого значения - это с плавающей точкой.Вы заметите, что я поместил ключевое слово rec в нашу рекурсивную функцию, лучше явно объявить всякий раз, когда вы создаете рекурсивную функцию.

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