我在使用一个函数来删除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天才能指出我为什么是个笨蛋。
发布于 2012-10-31 04:25:32
这里你所需要的就是操作符部分的以下三条“定律”:
(a `op` b) = (a `op`) b = (`op` b) a = op a b
(1) (2) (3)这样操作数就会进入运算符附近的空闲位置。
对于(.),这意味着:(a . b) = (a .) b = (. b) a = (.) a b。所以,
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你应该只做你喜欢的无点转换,这样得到的表达式对你来说仍然是可读的--事实上,比原始表达式更清晰。“无指针”工具有时会产生不可读的结果。
在中间停下来是完全可以的。
((a .) . b) x y = (a .) (b x) y = (a . b x) y = a (b x y)是一种常见的模式,您将很快学会立即识别。因此,上面的表达式可以很容易地回读为
(!!) ((f . g) x y) n = f (g x) y !! n考虑到(.)是关联的:
(a . b . c) = ((a . b) . c) = (a . (b . c))发布于 2012-10-30 21:27:46
funcB = ((!!) .) . iterate . funcA我想你已经完成了所有的艰苦工作,只剩下一小步了。
您确实可以使用pointfree自动完成此操作。请参阅HaskellWiki page
正如它在github readme中所说的,一旦您安装了它,您就可以使用下面的代码行编辑您的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发布于 2012-10-31 01:45:23
对我来说,关键的观察结果是中缀操作符可以写为prefix:
funcB as = (!!) . (iterate . funcA) as
funcB as = (.) (!!) ((iterate . funcA) as)一旦你到了这里,你就有一半的机会认识到这是一个组合,第一个参数是(.) (!!),第二个参数是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)https://stackoverflow.com/questions/13139969
复制相似问题