【发布时间】:2014-02-28 19:18:11
【问题描述】:
我从编译器的建议中发现了一些对我来说似乎很奇怪的东西。
我做了一个数据类型来表示二进制数如下:
data Bin = Zero | One
我选择将多位二进制数表示为 Bin 类型的列表,如下所示:
myNum :: [Bin]
myNum = [One, Zero, One, One] -- represents the number 1011
当然,我想以更方便的方式显示我的二进制数,所以我创建了一个 Show 实例来为我做这件事:
instance Show Bin where
show Zero = "0"
show One = "1"
showList [] = showString ""
showList (x:xs) = showString (show x) . showList xs
这有效,print myNum 正确显示 1011。
我还是 Haskell 的新手,这是我第一次使用 showList。但这对我来说很有意义。由于 showList 的类型为 [a] -> ShowS(它本身是 [a] -> (String -> String) 的别名),我知道我通过使用函数组合来“连接”列表的元素。但是编译器建议我把showList函数重新定义一下:
Warning: Use foldr
Found:
showList [] = showString ""
showList (x : xs) = showString (show x) . showList xs
Why not:
showList xs = foldr ((.) . showString . show) (showString "") xs
而且,一旦我替换了它的建议,它就提出了进一步的建议:
Error: Eta reduce
Found:
showList xs = foldr ((.) . showString . show) (showString "") xs
Why not:
showList = foldr ((.) . showString . show) (showString "")
我了解 Eta reduce 错误,因为通常最好编写无点函数。但我在第一次转换时遇到了麻烦。我看到foldr 的第二个参数是“基本情况”正确身份,但我很难理解foldr 的第一个参数中发生了什么。所以我有两个问题:
- 如何重写
((.) . showString . show)?比如我知道(f . g) x可以改写成f (g x)。 - 这在
foldr的上下文中实际上做了什么?
【问题讨论】:
-
您可能还想将
showString . show简化为shows,这应该总是做同样的事情,但可能更有效。事实上,您可以将所有这些简化为showList xs s = foldr shows s xs,甚至是showList = flip foldr shows。
标签: haskell functional-programming abstract-data-type