수색…


소수의 예와 함께 접기에 대한 소개

폴드는 일련의 요소와 함께 사용되는 (고차원) 함수입니다. 그들은 seq<'a>'b seq<'a> 붕괴시킵니다. 여기서 'b 는 어떤 유형입니까 (여전히 'a ). 이것은 약간 추상적이어서 구체적인 실제 예를 들어 볼 수 있습니다.

모든 숫자의 합 계산

이 예제에서 'aint 입니다. 우리는 숫자의 목록을 가지고 있고 그것을 합계로 계산하려고합니다. 목록의 수를 합하려면 [1; 2; 3] 쓰고 있습니다

List.fold (fun x y -> x + y) 0 [1; 2; 3] // val it : int = 6

우리가리스트를 다루기 때문에 List 모듈에서 fold 를 사용하므로 List.fold 합니다. 첫 번째 인수 fold 는 이진 함수 인 폴더 입니다. 두 번째 인수는 초기 값 입니다. fold 는 폴더 함수를 초기 값과 첫 번째 요소로 시작하는 목록의 요소에 연속적으로 적용하여 목록을 fold 시작합니다. 목록이 비어 있으면 inital 값이 반환됩니다!

실행 예제의 개요는 다음과 같습니다.

let add x y = x + y // this is our folder (a binary function, takes two arguments)
List.fold add 0 [1; 2; 3;]
=> List.fold add (add 0 1) [2; 3] 
// the binary function is passed again as the folder in the first argument
// the initial value is updated to add 0 1 = 1 in the second argument
// the tail of the list (all elements except the first one) is passed in the third argument
// it becomes this:
List.fold add 1 [2; 3]
// Repeat untill the list is empty -> then return the "inital" value
List.fold add (add 1 2) [3]
List.fold add 3 [3] // add 1 2 = 3
List.fold add (add 3 3) [] 
List.fold add 6 [] // the list is empty now -> return 6
6

List.sum 함수는 대충 List.fold add LanguagePrimitives.GenericZero 여기서 제로 제로는 정수, 부동 소수점, 큰 정수 등과 호환됩니다.

목록에서 elemets 계산 ( count 구현)

위와 거의 동일하지만 목록의 요소 값을 무시하고 대신 1을 더합니다.

List.fold (fun x y -> x + 1) 0 [1; 2; 3] // val it : int = 3

이것은 또한 이렇게 할 수 있습니다 :

[1; 2; 3]
|> List.map (fun x -> 1) // turn every elemet into 1, [1; 2; 3] becomes [1; 1; 1]
|> List.sum // sum [1; 1; 1] is 3

그래서 count 를 다음과 같이 정의 할 count 있습니다 :

let count xs = 
    xs 
    |> List.map (fun x -> 1) 
    |> List.fold (+) 0 // or List.sum

최대 목록 찾기

이번에는 List.fold 와 같은 List.reduce 를 사용할 것입니다. 그러나이 경우와 같이 초기 값이없는 경우에는 우리가 생성하는 값의 유형이 무엇인지 알 수 없습니다.

let max x y = if x > y then x else y
// val max : x:'a -> y: 'a -> 'a when 'a : comparison, so only for types that we can compare
List.reduce max [1; 2; 3; 4; 5] // 5
List.reduce max ["a"; "b"; "c"] // "c", because "c" > "b" > "a"
List.reduce max [true; false] // true, because true > false 

목록의 최소값 찾기

최대 값을 찾을 때와 마찬가지로 폴더가 다릅니다.

let min x y = if x < y then x else y
List.reduce min [1; 2; 3; 4; 5] // 1
List.reduce min ["a"; "b"; "c"] // "a"
List.reduce min [true; false] // false

리스트 연결하기

여기서 우리는 목록의 목록을 취합니다 폴더 함수는 @ 연산자입니다

// [1;2] @ [3; 4] = [1; 2; 3; 4]
let merge xs ys = xs @ ys
List.fold merge [] [[1;2;3]; [4;5;6]; [7;8;9]] // [1;2;3;4;5;6;7;8;9]

또는 이진 연산자를 폴더 함수로 사용할 수 있습니다.

List.fold (@) [] [[1;2;3]; [4;5;6]; [7;8;9]] // [1;2;3;4;5;6;7;8;9]
List.fold (+) 0 [1; 2; 3] // 6
List.fold (||) false [true; false] // true, more on this below
List.fold (&&) true [true; false] // false, more on this below
// etc...

숫자의 계승 계산

숫자를 합산 할 때와 같은 생각이지만, 이제는 곱합니다. 우리가 n 의 계승을 원하면 목록 [1 .. n] 의 모든 요소를 ​​곱합니다. 코드는 다음과 같습니다.

// the folder
let times x y = x * y
let factorial n = List.fold times 1 [1 .. n]
// Or maybe for big integers
let factorial n = List.fold times 1I [1I .. n] 

forall , existscontains 구현

forall 함수는 시퀀스의 모든 요소가 조건을 만족하는지 확인합니다. exists 리스트이어야 하나 개의 요소가 상기 조건을 만족하는 경우에 확인. 먼저 bool 값 목록을 bool 방법을 알아야합니다. 글쎄, 우리는 폴드를 사용합니다! 부울 연산자는 우리의 폴더 함수가 될 것입니다.

리스트의 모든 원소가 true 인지를 검사하기 위해 초기 값으로 true 를 가진 && 함수를 사용하여 원소를 붕괴합니다.

List.fold (&&) true [true; true; true] // true
List.fold (&&) true [] // true, empty list -> return inital value
List.fold (&&) true [false; true] // false

마찬가지로, 목록 요소에서 하나의 요소가 true 인지 확인하려면 부울 값을 || 초기 값으로 false 를 갖는 연산자 :

List.fold (||) false [true; false] // true
List.fold (||) false [false; false] // false, all are false, no element is true
List.fold (||) false [] // false, empty list -> return inital value

forall 돌아가서 exists . 여기서 모든 유형의 목록을 가져와 조건을 사용하여 모든 요소를 ​​부울 값으로 변환 한 다음 축소합니다.

let forall condition elements = 
    elements 
    |> List.map condition // condition : 'a -> bool
    |> List.fold (&&) true

let exists condition elements = 
    elements
    |> List.map condition
    |> List.fold (||) false

[1; 2; 삼; 4]가 5보다 작 으면 :

forall (fun n -> n < 5) [1 .. 4] // true

exists 사용하여 contains 메소드를 정의하십시오.

let contains x xs = exists (fun y -> y = x) xs

또는

let contains x xs = exists ((=) x) xs

이제 목록 [1. .. 5]에 값 2가 포함되어 있는지 확인하십시오.

contains 2 [1..5] // true

reverse 구현 :

let reverse xs = List.fold (fun acc x -> x :: acc) [] xs
reverse [1 .. 5] // [5; 4; 3; 2; 1]

mapfilter 구현

let map f = List.fold (fun acc x -> List.append acc [f x]) List.empty
// map (fun x -> x * x) [1..5] -> [1; 4; 9; 16; 25]   

let filter p = Seq.fold (fun acc x -> seq { yield! acc; if p(x) then yield x }) Seq.empty
// filter (fun x -> x % 2 = 0) [1..10] -> [2; 4; 6; 8; 10]

fold 할 수없는 것이 있습니까? 나는 정말로 모른다.

목록의 모든 요소의 합계 계산

숫자 목록의 (float, int 또는 big integer 유형의) 용어 합계를 계산하려면 List.sum을 사용하는 것이 좋습니다. 다른 경우 List.fold는 이러한 합계를 계산하는 데 가장 적합한 함수입니다.

  1. 복소수의 합

이 예에서는 복소수 목록을 선언하고 목록의 모든 용어의 합계를 계산합니다.

프로그램 시작 부분에서 System.Numerics에 대한 참조를 추가하십시오.

System.Numerics를 엽니 다.

합을 계산하기 위해, 누산기를 복소수 0으로 초기화합니다.

let clist = [new Complex(1.0, 52.0); new Complex(2.0, -2.0); new Complex(0.0, 1.0)]

let sum = List.fold (+) (new Complex(0.0, 0.0)) clist

결과:

(3, 51)
  1. 유니온 타입의 합계

리스트가 여러 개의 union (float 또는 int) 유형으로 구성되어 있고 이들 숫자의 합을 계산하려고한다고 가정하십시오.

다음 번호 유형 앞에 선언하십시오.

type number = 
| Float of float
| Int of int

목록 유형 번호의 합계를 계산하십시오.

let list = [Float(1.3); Int(2); Float(10.2)]

let sum = List.fold (
                         fun acc elem -> 
                                        match elem with
                                        | Float(elem) -> acc + elem
                                        | Int(elem) -> acc + float(elem)
                        ) 0.0 list

결과:

13.5

누적기를 나타내는 첫 번째 매개 변수는 float 유형이고 목록의 항목을 나타내는 두 번째 매개 변수는 숫자 유형입니다. 그러나 우리가 추가하기 전에, elem이 Int 타입 일 때 float를 입력하기 위해 패턴 매칭과 캐스트를 사용해야합니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow