Haskell 美丽可怕的哈斯克尔

Haskell 美丽可怕的哈斯克尔,haskell,functional-programming,Haskell,Functional Programming,哈斯克尔很漂亮。这是事实。它简洁、快速等。你们中的许多人都会承认用它写作是一种极大的乐趣。另一方面,我认为当人们试图编写过于复杂的代码时,它的简洁性可能是一个缺点。例如,我最近打开了我朋友的项目,发现了如下内容: stationDepartures id sc=map (\(s1,list)->(stationName $ (stationMap $ system sc) Map.! s1,list)) ( Map.toList (Map.fromListWith (++) (map (\

哈斯克尔很漂亮。这是事实。它简洁、快速等。你们中的许多人都会承认用它写作是一种极大的乐趣。另一方面,我认为当人们试图编写过于复杂的代码时,它的简洁性可能是一个缺点。例如,我最近打开了我朋友的项目,发现了如下内容:

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))))))))

我完全看不懂这一行。这当然是一个非常极端的例子,但它帮助我认识到,可能我的Haskell代码对其他人来说似乎不可读。我开始想知道在Haskell中创建漂亮代码的原则是什么。我发现一些人认为lambda函数是多余的,因为它们会降低代码的可读性。你觉得怎么样?Haskell代码应该满足哪些要求才能被认为是“漂亮的”?

我假设您会问,“我如何才能以更可读的方式编写这一行程序?”否则,这个问题就太主观了

一行程序在任何语言中都是有问题的,尽管Haskell可能会特别有问题,因为二进制运算符(具有优先规则)、高阶函数(难以命名)和(gasp!)高阶函数都是二进制运算符。但是,我们可以首先注意到,大多数括号可以在一行中删除,并且我们可以显示表达式是由一系列函数组成的。每个函数都可以写在单独的一行上,由
组成,最后一行是
$
,用于将整个内容应用于参数

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
函数都将
Map
作为最后一个参数而不是第一个参数的原因。在设计Haskell API时请记住这一点!)

例如,
Map.toList。Map.fromlistwithf
模式非常常见,只是很难用一行代码(至少在我看来)看到它。代码并没有那么复杂,只是通过手术删除了它的换行符

但是,可读性是主观的。


你将形成一种易于阅读的风格。随着你对语言理解的加深,风格也会不断发展,你对“优美代码”的感觉也会不断发展。就让它发生吧,试着不要在重写中陷入太多你不再感兴趣的泥潭。

我建议你用更专业的方式重新表述你的问题。现在它可能因为过于主观而关闭。或者,询问允许和鼓励讨论的地方,例如。与此同时,大多数人都认为232个字符对于一行来说太长了。如果你对良好的Haskell风格感兴趣,你应该看看第一个
地图
可以通过
第二个
功能简化。我考虑过这一点,但我不想引入箭头。