2015-02-25 5 views
1

Я новичок в F # и задаю вопрос о конвейерах функций. Скажем, у нас есть функция map, которая отображает список функций на массив значений, создающих список массивов: примерF # Изменение параметров приоритета

//val map : ('a -> 'b) list -> 'a [] -> 'b [] list  
let map funcs vals = 
    funcs |> List.map (fun f -> Array.map f vals) 

Использование:

//val it : float [] list = [[|1.0; 1.144729886|]; [|15.15426224; 23.14069263|]] 
map [log; exp] [|Math.E; Math.PI|] 

Есть ли способ заменить лямбда-функции (fun f -> Array.map f vals) с сеть операторов трубопроводов?

Я хотел бы написать, как л:

//val map : 'a [] list -> ('a -> 'b) -> 'b [] list 
let map funcs vals = funcs |> List.map (vals |> Array.map) 

Но это не работает.

Большое спасибо,

Иван

ответ

2

Вы можете использовать этот.

let map funcs vals = funcs |> List.map (Array.map >> ((|>) vals)) 

Часть Array.map >> ((|>) vals) частично относится к fArray.map, а затем сочиняет его с применением vals.

+0

Спасибо за ответ! Возможно, это затрудняет чтение кода. –

0

Для меня самым читаемым функция кросс-продукт будет:

let flip f y x = f x y // a pretty standard function for flipping arguments of function 
let crossProduct funcs vals = 
    (<|) 
    >> flip Array.map vals 
    |> flip List.map funcs 

let result = crossProduct [log; exp] [|Math.E; Math.PI|] 

TL; DR: Немного объяснений.
Узор: xs |> List.map f очень популярен, но иногда лучше написать:
f |> List.map <| xs
Или, используя flip: f |> flip List.map xs
Учитывая это, давайте напишем функцию в наиболее простым способом:

let cartesianProduct0 funcs vals = 
    fun f -> 
     fun v -> f v 
     |> (flip Array.map vals) 
    |> (flip List.map funcs) 

Тогда вы заметили, что на самом деле fun v -> f v(<):

fun f -> 
    ((<|) f) 
    |> (flip Array.map vals) 

или:

fun f -> 
    f 
    |> (<|) 
    |> (flip Array.map vals) 

или просто:

(<|) 
>> flip Array.map vals 

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

Смежные вопросы