lob*_*ism 6 f# haskell scala pointfree
我有一个创建Async工作流的函数,以及以咖喱风格获取10个参数的函数.例如
let createSequenceCore a b c d e f g h i j =
async {
...
}
Run Code Online (Sandbox Code Playgroud)
我想创建另一个函数来启动该工作流程,所以我有
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)
Run Code Online (Sandbox Code Playgroud)
有什么办法可以摆脱那些多余的参数吗?我尝试了<<
操作员,但这只能让我删除一个.
let startSequenceCore a b c d e f g h i =
Async.StartImmediate << (createSequenceCore a b c d e f g h i)
Run Code Online (Sandbox Code Playgroud)
(我将Haskell和Scala添加到这个问题中,即使代码本身是F#,我真正想要的是如何做这种currying,这适用于任何;我认为Haskell或Scala的答案很容易便携式到F#,很可能被标记为正确的答案).
注意合理地表明没有一个简单的解决方案也可以得到赏金.
更新 geesh我不会给出一个与问题争论的答案而不是回答100分,即使它是最高的投票,所以这里:
我有一个创建Async工作流的函数,以及以咖喱风格获取4个参数的函数.例如
let createSequenceCore a b c d =
async {
...
}
Run Code Online (Sandbox Code Playgroud)
我想创建另一个函数来启动该工作流程,所以我有
let startSequenceCore a b c d =
Async.StartImmediate (createSequenceCore a b c d)
Run Code Online (Sandbox Code Playgroud)
有什么办法可以摆脱那些多余的参数吗?我尝试了<<
操作员,但这只能让我删除一个.
let startSequenceCore a b c =
Async.StartImmediate << (createSequenceCore a b c)
Run Code Online (Sandbox Code Playgroud)
10个参数听起来太多了......你怎么用10个属性来创建一个记录,或者在每个情况下你不需要全部10个属性的DU?无论哪种方式,你最终会得到一个单一的参数,正常的函数组合再次按预期工作.
编辑:当你真正需要它,你可以创建一个更强大的版本<<
,并>>
正是如此运营商:
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
Run Code Online (Sandbox Code Playgroud)
然后你可以写:
let startSequenceCore =
Async.StartImmediate <...< createSequenceCore
Run Code Online (Sandbox Code Playgroud)
要么
let startSequenceCore =
createSequenceCore >...> Async.StartImmediate
Run Code Online (Sandbox Code Playgroud)
PS:论证f
就在那里,因此类型推断推断出通用的args而不是obj
.
正如@Daniel Fabian已经提到的,10个论点太多了.根据我的经验,即使5个参数太多,代码也变得难以理解且容易出错.具有这样的功能通常表示设计不良.另请参阅有关函数应接受的参数数量的指南吗?
但是,如果你坚持,有可能让它无点,尽管我怀疑它会带来什么好处.我将在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
Run Code Online (Sandbox Code Playgroud)
替换f
为(f .)
提升函数以在其中处理一个参数,我们可以通过在以下类型中添加括号来看到(.)
:
(.) :: (b -> c) -> ((a -> b) -> (a -> c))
Run Code Online (Sandbox Code Playgroud)
另请参阅Conal Elliott撰写的这篇有启发性的博客文章:语义编辑器组合