我在与钻营的功能,在Haskell除去三个参数的麻烦。
免责声明:未习作,有人问我有人有这个挣扎今天这个问题和它的被窃听我。
我们给出的自定义类型/职能是(只能记住类型)
type MyThing
= (Char, String)
type MyThings
= [MyThing]
funcA :: MyThings -> String -> String
funcB :: MyThings -> String -> Int -> String
我们开始:
funcB as str n = iterate (funcA as) str !! n
并降低其具体情况如下:
funcB as str n = iterate (funcA as) str !! n
funcB as str = (!!) . (iterate (funcA as)) str
funcB as = (!!) . (iterate (funcA as))
funcB as = (!!) . (iterate . funcA) as
然后,卡住了。 我们只是无法弄清楚如何避免使用最后一个参数。 我知道我以前在什么地方见过类似的情况,有一个解决方案。
希望一些Haskell的天才可以指出为什么我是一个傻瓜...
所有你需要的这里是操作部分的三个“规律”:
(a `op` b) = (a `op`) b = (`op` b) a = op a b
(1) (2) (3)
从而使操作进入操作附近的空闲插槽。
为(.)
这意味着: (a . b) = (a .) b = (. b) a = (.) ab
所以,
f (g x) y !! n
= (!!) (f (g x) y) n by (3)
= ((!!) . f (g x)) y n
= ((!!) . (f . g) x) y n
= ((!!) .) ((f . g) x) y n by (1)
= (((!!) .) . (f . g)) x y n
= (((!!) .) . f . g) x y n
当你感到满意时,才应做尽可能多pointfree改造,使产生的表达式仍然可读适合你 -而事实上,比原来更清晰 。 该“pointfree”工具有时可以产生不可读的结果。
它也完全可以在中途停止。 如果是太难为你手工完成它,因为这可能是你很难读它了。
((a .) . b) xy = (a .) (bx) y = (a . bx) y = a (bxy)
是,你很快就能学会立即识别常见的模式 。 因此,上述表达式可以回读很容易的
(!!) ((f . g) x y) n = f (g x) y !! n
考虑到(.)
是关联:
(a . b . c) = ((a . b) . c) = (a . (b . c))
funcB = ((!!) .) . iterate . funcA
我认为你做所有的辛勤工作,并有一只离开寸步。
你可以用确实这样做自动pointfree 。 见HaskellWiki页
由于它在说github上自述 ,一旦你安装了它,您可以编辑ghci.conf
或.ghci
一行的文件
:def pf \str -> return $ ":! pointfree \"" ++ str ++ "\""
然后在ghci中,当你键入
:pf funcB as = (!!) . (iterate . funcA) as
甚至
:pf funcB as str n = iterate (funcA as) str !! n
你得到
funcB = ((!!) .) . iterate . funcA
对我来说 ,关键的发现是,中缀运算符可以写成前缀:
funcB as = (!!) . (iterate . funcA) as
funcB as = (.) (!!) ((iterate . funcA) as)
一旦你在这里得到了,你必须认识到这是一种组合物,用一半的机会(.) (!!)
作为第一个参数和iterate . funcA
iterate . funcA
作为第二个参数:
funcB as = ( ((.) (!!)) . (iterate . funcA) ) as
现在很清楚如何简化这一点; 在那之后,有很多关于如何写出来的审美选择。 例如,我们可以观察到, (.)
是关联的,所以我们可以减少一些括号; 同样,我们可以使用运营商的部分合并难看((.) (!!))
如果你认为它是更具可读性的方式。
funcB = ( ((.) (!!)) . (iterate . funcA) )
funcB = (.) (!!) . iterate . funcA -- uncontroversial parenthesis removal
funcB = ((!!) .) . iterate . funcA -- possibly controversial section rewrite
顺便说一句,我不认为你的推导的开始是正确的。 您到达了正确的结论,而是通过不正确中间环节。 更正,应该是这样的:
funcB as str n = iterate (funcA as) str !! n
funcB as str n = (!!) (iterate (funcA as) str) n
funcB as str = (!!) (iterate (funcA as) str)
funcB as = (!!) . iterate (funcA as)