Seq.fold и логический аккумулятор - PullRequest
3 голосов
/ 18 октября 2010

Я никогда не могу найти исходный код основных библиотек F #.Я знаю, что это, предположительно, open , но Google не очень-то добр ко мне, помогая мне найти его, в таком случае я бы посмотрел значение Seq.fold - но здесь возникает вопрос.

Кто-нибудь видит какие-либо проблемы со следующим фрагментом:

let success = myList |>
                    Seq.fold 
                        (fun acc item -> evaluation item)
                        false 

Логически, похоже, он не удерживает воду, и я могу и буду экспериментировать, чтобы проверить это.Но я хотел спросить сообщество.Если какая-либо отдельная оценка внутри myList возвращает значение false, я хочу, чтобы переменная успеха была ложной ...


Итак, тест:

let myList = [true; true]
let success = List.fold (fun acc item -> acc && item) true myList

и

let myList = [true; false; true]
let success = List.fold (fun acc item -> acc && item) true myList

верните правильные результаты - мне было бы удобнее увидеть источник ...

Ответы [ 6 ]

4 голосов
/ 18 октября 2010

Seq.exists будет короткое замыкание:

let success = 
  [1;2;3;40;5;2] 
  |> Seq.exists (fun item->(item>30))
  |> not
4 голосов
/ 18 октября 2010

Я думаю, что вы ищете что-то вроде этого:

let success = myList |>
                    Seq.fold
                        (fun acc item -> acc && evaluation item)
                        true

Это также предлагает оценку "короткого замыкания", так что если acc = false от предыдущей оценки, evaluation item не будет выполняться, а выражение просто вернет false.

Документация MSDN для оператора сгиба

1 голос
/ 18 октября 2010

Хмммм, я недавно обновил Visual Studio и F # и, похоже, не могу найти каталог, содержащий код библиотеки F #.Но, как бы то ни было, Seq.fold эквивалентен следующему:

let fold f seed items =
    let mutable res = seed
    for item in items do
        res <- f res item
    res

Если какая-либо отдельная оценка внутри myList возвращает значение false, я хочу, чтобы переменная успеха была ложной ...

Это зависит от того, как реализована ваша функция evaluation.Если вы хотите вернуть значение false, если любой из ваших элементов имеет значение false, вместо этого используйте Seq.forall.

0 голосов
/ 23 ноября 2017

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

О конкретном вопросе здесь

Тамуже существует функция, которая возвращает false, как только один элемент в последовательности является ложным: Seq.forAll.

Таким образом, на самом деле самый простой ответ на вопрос:

let success = Seq.forAll evaluation myList

, чтонемного легче понять, чем (переписанный) ответ TechNeilogy

let success = not (Seq.exists evaluation myList)

Оба в принятый ответ Уэсли Вайзера , и в этом ответе функция evaluationне оценивается на предметах после первого предмета, который оценивает сложение.Но, как правильно заметил Паскаль Куок, в принятом ответе все элементы остальной части списка все еще повторяются, что бесполезно.Напротив, Seq.forAll действительно прекращает итерации, когда нет смысла продолжать.То же самое можно сказать и о Seq.exists, Seq.takeWhile,…

о коротком замыкании сгиба в целом

В других случаях требуется короткое замыкание сгиба,Это может быть сделано.

Шаг 1: Определите папку с некоторой индикацией того, что состояние не изменится во время обхода остальной части исходной последовательности, и свертывание должно бытькороткое замыкание.

Шаг 2: Используйте Seq.scan вместо fold.Seq.scan аналогично fold, принимает те же аргументы, но вычисляет по требованию и возвращает не только конечное состояние, но и последовательность всех промежуточных состояний и конечное состояние.Отсюда следует: Seq.last (Seq.scan folder initialState mySequence) = Seq.fold folder initialState mySequence

Шаг 3: Используйте функцию короткого замыкания на выходе Seq.scan.Выберите: Seq.takeWhile, Seq.forall, Seq.exists,…

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

let allDistinct mySequence =
    let folder state element =
        match state with
            | Some elementsSoFar when not (Set.contains element elementsSoFar) ->
                Some (Set.add element elementsSoFar)
            | _ ->
                None
    let initialState = Some Set.empty
    let scanning = Seq.scan folder initialState mySequence
    Seq.forall Option.isSome scanning
0 голосов
/ 21 октября 2010

Что касается оригинального источника, то здесь представлены функции свертки из выпуска от 10 августа 2010 года.

На самом деле не нужно беспокоиться о реализации, но ее рассмотрение часто может быть полезным.

// Seq module
let fold<'T,'State> f (x:'State) (source : seq<'T>)  = 
    checkNonNull "source" source
    use e = source.GetEnumerator() 
    let mutable state = x 
    while e.MoveNext() do
        state <- f state  e.Current;
    state


// Array module
let fold<'T,'State> (f : 'State -> 'T -> 'State) (acc: 'State) (array:'T[]) = //'
    checkNonNull "array" array
    let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
    let mutable state = acc 
    let len = array.Length
    for i = 0 to len - 1 do 
        state <- f.Invoke(state,array.[i])
    state


// List module
let fold<'T,'State> f (s:'State) (list: 'T list) = 
    match list with 
    | [] -> s
    | _ -> 
        let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
        let rec loop s xs = 
            match xs with 
            | [] -> s
            | h::t -> loop (f.Invoke(s,h)) t
        loop s list


// MapTree module (Used by Map module)
let rec fold (f:OptimizedClosures.FSharpFunc<_,_,_,_>) x m  = 
    match m with 
    | MapEmpty -> x
    | MapOne(k,v) -> f.Invoke(x,k,v)
    | MapNode(k,v,l,r,_) -> 
        let x = fold f x l
        let x = f.Invoke(x,k,v)
        fold f x r

// Map module
let fold<'Key,'T,'State when 'Key : comparison> f (z:'State) (m:Map<'Key,'T>) = //'
    let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f)
    MapTree.fold f z m.Tree


// SetTree module (Used by Set module)
let rec fold f x m = 
    match m with 
    | SetNode(k,l,r,_) -> 
        let x = fold f x l in 
        let x = f x k
        fold f x r
    | SetOne(k) -> f x k
    | SetEmpty -> x

// Set module
let fold<'T,'State  when 'T : comparison> f (z:'State) (s : Set<'T>) = //'
    SetTree.fold f z s.Tree
0 голосов
/ 18 октября 2010

что-то вроде этого

let l = [true; true; true; false; true]

let eval x = x

let x = (true, l) ||> Seq.fold(fun acc item -> acc && (eval item))

или вы хотите остановить оценку при первом ложном результате?

let l = [true; false; true]

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