4

Haskell is beautiful. That's a fact. It's concise, fast etc. Many of you will admit that writing in it is a great pleasure. On the other hand I think that its conciseness might be a disadvantage when people try to write too sophisticated code. For example I recently opened my friend's project and found something like this:

stationDepartures id sc=map (\(s1,list)->(stationName $ (stationMap $ system sc) Map.! s1,list)) ( Map.toList (Map.fromListWith (++) (map (\((s1,s2),(d,start,dur))->(s2,[start])) (Map.toList (Map.filterWithKey (\(s1,s2) _ ->s1==id) (Map.unions (List.map times (Map.elems $ schedule sc))))))))

This one-liner was absolutely unreadable to me. This is of course a quite extreme example but it helped me to realize that maybe my Haskell code might seem unreadable to others. I started to wonder what are the principles of creating a beautiful code in Haskell. I found that e.g. lambda functions are considered by some people as superfluous because they make the code less readable. What do you think about that? What requirements should Haskell code meet to be considered as "beautiful"?

4

1 回答 1

20

我将假设您问:“我怎样才能以更易读的方式编写这个单行代码?” 否则,这个问题有点太主观了。

单线在任何语言中都是有问题的,尽管 Haskell 尤其有问题,因为有大量的二元运算符(有优先规则)、高阶函数(很难命名)和(喘气!)高阶函数二元运算符。但是,我们可以首先注意到单行中的大部分括号都可以去掉,我们可以证明表达式是一系列组合在一起的函数。每个函数都可以写在单独的行上,并由 组成.,最后$将整个事物应用于参数。

stationDepartures id sc =
  map (\(s1,list) -> (stationName $ (stationMap $ system sc) Map.! s1,
                      list)) .
  Map.toList .
  Map.fromListWith (++) .
  map (\((s1,s2),(d,start,dur)) -> (s2,[start])) .
  Map.toList .
  Map.filterWithKey (\(s1,s2) _ -> s1 == id) .
  Map.unions .
  List.map times .
  Map.elems $ schedule sc

对我来说,这是相当易读的,因为我可以识别其中的模式,并且我可以从下到上跟踪数据流。(注意:这就是为什么所有Map函数都将 aMap作为最后一个参数而不是第一个参数的原因。在设计 Haskell API 时请记住这一点!)

例如,这种Map.toList . Map.fromListWith f模式很常见,只是很难在单眼线中看到它(至少在我看来)。代码并没有那么复杂,只是通过手术去除了换行符。

但是,可读性是主观的。

您将开发一种易于阅读的风格。随着你对语言的了解越多,风格就会进化,你对“漂亮代码”的感觉也会进化。让它发生,尽量不要在重写中陷入太多的泥潭,因为你不再有乐趣了。

于 2012-06-20T22:22:54.260 回答