2014-02-07 3 views
6

У меня есть функция, которая создает рабочий процесс Async и функцию, которая принимает 10 аргументов в стиле карри. напримерКак сделать точечный стиль с длинным списком параметров

let createSequenceCore a b c d e f g h i j = 
    async { 
    ... 
    } 

Я хочу, чтобы создать еще одну функцию, чтобы начать этот рабочий процесс, так что я получил

let startSequenceCore a b c d e f g h i j = 
    Async.StartImmediate (createSequenceCore a b c d e f g h i j) 

Есть ли способ, я могу избавиться от этих избыточных параметров? Я попробовал оператор <<, но это только позволяет мне удалить его.

let startSequenceCore a b c d e f g h i = 
    Async.StartImmediate << (createSequenceCore a b c d e f g h i) 

(я добавил Haskell и Scala на этот вопрос, даже если сам код F #, так как на самом деле то, что я хочу, это просто, как сделать этот вид выделки, который применим к любому, я думаю, Ответ Haskell или Scala был бы легко переносимым на F # и мог бы быть отмечен как правильный ответ).

УКАЗАНИЕ Разумно хорошо показать, что это нелегкое решение для этого также может получить щедрость.


UPDATE geesh Я не собираюсь дать 100 очков, чтобы дать ответ, который спорит с вопросом, а не отвечая на него, даже если это наибольшее количество голосов, поэтому здесь:

Я получил функцию, которая создает рабочий процесс Async, и функцию, которая принимает аргументы в стиле карри. например

let createSequenceCore a b c d = 
    async { 
    ... 
    } 

Я хочу, чтобы создать еще одну функцию, чтобы начать этот рабочий процесс, так что я получил

let startSequenceCore a b c d = 
    Async.StartImmediate (createSequenceCore a b c d) 

Есть ли способ, я могу избавиться от этих избыточных параметров? Я попробовал оператор <<, но это только позволяет мне удалить его.

let startSequenceCore a b c = 
    Async.StartImmediate << (createSequenceCore a b c) 
+0

Добавлен более полный ответ как редактирование, пожалуйста, проверьте его. –

ответ

9

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

EDIT: Когда вы на самом деле нужно, вы можете создать более мощную версию << и >> операторов Thusly:

let (<.<) f = (<<) (<<) (<<) f 
let (<..<) f = (<<) (<<) (<.<) f 
let (<...<) f = (<<) (<<) (<..<) f 

let flip f a b = f b a 
let (>.>) f = flip (<.<) f 
let (>..>) f = flip (<..<) f 
let (>...>) f = flip (<...<) f 

, а затем вы можете просто написать:

let startSequenceCore = 
    Async.StartImmediate <...< createSequenceCore 

или

let startSequenceCore = 
    createSequenceCore >...> Async.StartImmediate 

P.S .: Аргумент f есть, так что тип вывода выводит общие аргументы, а не obj.

2

Вы могли бы кортеж аргументы createSequenceCore:

let createSequenceCore(a, b, c, d, e, f, g, h, i, j) = 
    async { 
    ... 
    } 

let startSequenceCore = 
    createSequenceCore >> Async.StartImmediate 
+0

Я переупорядочил функции в 'startSequenceCore', чтобы его можно было читать влево-вправо, как это было бы с оператором' |> '. – mydogisbox

6

Как уже упоминалось @Daniel Fabian, 10 аргументов слишком много. По моему опыту даже 5 аргументов слишком много, и код становится нечитаемым и подвержен ошибкам. Наличие таких функций обычно сигнализирует о плохом дизайне. См. Также Are there guidelines on how many parameters a function should accept?

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

data Test = Test 
    deriving (Show) 

createSequenceCore :: Int -> Int -> Int -> Int -> Int 
        -> Int -> Int -> Int -> Int -> Int -> Test 
createSequenceCore a b c d e f g h i j = Test 

-- the original version 
startSequenceCore :: Int -> Int -> Int -> Int -> Int 
        -> Int -> Int -> Int -> Int -> Int -> IO() 
startSequenceCore a b c d e f g h i j = 
    print (createSequenceCore a b c d e f g h i j) 

-- and point-free: 
startSequenceCore' :: Int -> Int -> Int -> Int -> Int 
        -> Int -> Int -> Int -> Int -> Int -> IO() 
startSequenceCore' = 
    (((((((((print .) .) .) .) .) .) .) .) .) . createSequenceCore 

Замена f с (f .) поднимает функцию, чтобы работать один аргумент внутри, как мы можем видеть, добавляя скобки к типу (.):

(.) :: (b -> c) -> ((a -> b) -> (a -> c)) 

См. Также это освещающее сообщение блога Коналом Эллиотом: Semantic editor combinators

+1

У меня возникает соблазн сказать, что 10 из _anything_ слишком много, если это происходит без значимого уровня абстракции. Как [если вы столкнулись с числом выше 8,7, вы не делаете настоящие математические данные] (http://xkcd.com/899/). – leftaroundabout

+0

@leftaroundabout Ницца! –

1

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

Просто напишите свою собственную функцию compN.

let compose4 g f x0 x1 x2 x4 = 
    g (f x0 x1 x2 x4) 

let startSequenceCore = 
    compose4 Async.StartImmediate createSequenceCore