2010-10-18 2 views
3

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

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

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

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


Так тест:

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 

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

+0

Для решения этой проблемы вы также можете использовать Seq.exists и отрицать результат. – TechNeilogy

+0

Или Seq.forall, что то же самое минус отрицание. (как упомянуто Juliet ниже) –

+1

Если вы хотите исходный код F #, он является частью CTP. Источник не поставляется с VS, а только CTP. http://www.microsoft.com/downloads/en/details.aspx?FamilyID=f8c623ae-aef6-4a06-a185-05f59be47d67&displaylang=en – Brian

ответ

3

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

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

Это также предлагает «краткосрочные circut» оценка, так что если АСС false от предыдущей оценки, evaluation item не будет работать, и выражение просто вернет false.

MSDN documentation for fold operator

+0

lol - Y Я заметил, как я изменял свой пример из сложного футляра в моем исходном источнике, чтобы что-то поместиться, я пропустил AND. Но спасибо ... Кажется, что это работает, но я не чувствую, что раньше я видел сгиб, используемый в сух ... – akaphenom

+0

@akaphenom fold - это просто функция накопления. Накопление булевых значений будет использовать логические операторы (&&, || и т. Д.), Так как накопление числовых значений будет использовать математические операторы (+, -, *, \ и т. Д.). –

+2

Это приведет к короткому замыканию вызова ' , но не (бесполезные) итерации в оставшейся части списка. –

0

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

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 
1

Хммм, я модернизировал свой 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 Retruns ложь, я хочу успех переменной ложными ...

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

+0

Да, 'Seq.forall', кажется, правильный путь. –

4

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

let success = 
    [1;2;3;40;5;2] 
    |> Seq.exists (fun item->(item>30)) 
    |> not 
+2

Заставляет меня думать о мире Уэйна. «Предмет больше 30 существует. НЕ!» – bentayloruk

0

Что касается первоисточника, вот кратные функции от 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

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

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

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

Так самый простой ответ на этот вопрос на самом деле:

let success = Seq.forAll evaluation myList 

, который немного легче понять, чем TechNeilogy’s (rewritten) answer

let success = not (Seq.exists evaluation myList) 

И в the accepted answer by Wesley Wiser и в этом ответе, функция evaluation не оценивается по элементам после первого элемента, который оценивает сброс. Но, как правильно заметил Паскаль Куок, в the accepted answer все элементы оставшейся части списка по-прежнему повторяются, что бесполезно. Напротив, 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