热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Haskell中的语法糖

在Wiki里关于语法糖的一些历史介绍: 语法糖(Syntactic sugar),是由Peter J. Landin(和图灵一样的天才人物,是他最先发现了Lambda演算&

在Wiki里关于语法糖的一些历史介绍:
语法糖(Syntactic sugar),是由Peter J. Landin(和图灵一样的天才人物,是他最先发现了Lambda演算,由此而创立了函数式编程)
创造的一个词语,它意指那些没有给计算机语言添加新功能,而只是对人类来说更“甜蜜“的语法。语法糖往往给程序员提供了更实用的
编码方式,有益于更好的编码风格,更易读。不过其并没有给语言添加什么新东西。

Wiki里提到,在C语言里用a[n]表示*(a+n),用a[n][m]表示*(*(a+n)+m),也是语法糖。
实际上从面向过程到面向对象也是一种语法糖,C语言可以通过它的指针、类型转换,结构实现面向对象的编程风格,
但是C++更进一步的推广了这种风格,更好用了。

按照Wiki的理解,只有计算机硬件指令才不算语法糖,而其他一切利用编译器、汇编器将代码抽象,和自然语言更相近的手段都算语法糖。[/color]


现在我们介绍一下 Haskell 中的语法糖,[color=Blue]如有错误,请指正,改之[/color]
[color=Red]1.缩进[/color]
Haskell 也像 C 语言一样可以用大括号 '{}' 和分号 ';' 来构造程序块,但这样的写法会造成程序难以阅读,为了解决这个问题,Haskell 引入了缩进。
注意 Haskell 的缩进不同于 Python 的缩进。在 Python 中,tab/空格 是语法,而 Haskell 中 tab/空格 是定义良好的语法糖,最终会被转换成
括号和分号的程序块的语法。

使用缩进的结构有:let,where,case of,... ? (其他的就不了解了)。在它们之后的缩进都可以转换为括号和分号的程序块语法。

[color=Red]2.Section[/color]
Section 最终会转换为 lambda 函数
例:



(+2)



=> /x -> x+2







(*2)



=> /x -> x*2





[color=Red]3.List[/color]

List 的最终转换如下:



[1, 2, 3, 4] => 1:2:3:4:[]



[1..10] => enumFromTo 1 10



[1, 3..10] => enumFromThenTo 1 3 10



[1..] => enumFrom 1



[1, 3..] => enumFromThen 1 3







Prelude> :t enumFrom



enumFrom :: (Enum a) => a -> [a]



Prelude> :t enumFromTo



enumFromTo :: (Enum a) => a -> a -> [a]



Prelude> :t enumFromThen



enumFromThen :: (Enum a) => a -> a -> [a]



Prelude> :t enumFromThenTo



enumFromThenTo :: (Enum a) => a -> a -> a -> [a]







Prelude> enumFromTo 1 10



[1,2,3,4,5,6,7,8,9,10]



Prelude> enumFromThenTo 1 3 10



[1,3,5,7,9]



Prelude> enumFrom 1



[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20



...



...



15732,15733,15Interrupted.





[color=Red]4.String[/color]

String 其实也是 List,之所以把它单独列出来,是因为 String 和 List 写法不一样,前者被双引号括住,而后者被中括号括住

String 的最终转换如下:



"abcde" => 'a':'b':'c':'d':'e':[]





[color=Red]5.List Comprehensions[/color]

List Comprehensions 等同于 map, filter 函数,但比 map, filter 函数更直观。

List Comprehensions 的最终转换如下:



[ x | x <- aList , f x] 



&#61;> 



let ok x &#61; if f x



then [x] 



else []



in concatMap ok aList







Prelude> :t concatMap



concatMap :: (a -> ) -> [a] -> 







[color&#61;Red]6.do[/color]
do 也是语法糖&#xff0c;但现在对 monad 还完全不了解&#xff0c;就不说了&#xff0c;如果以后有机会再补上。

[color&#61;Red]7. infix/prefix[/color]
引用 Magicloud 的原话
1 &#43; 2 等效于 (&#43;) 1 2
take 1 [0, 1] 等效于 1 &#96;take&#96; [0, 1]
无论是 (&#43;) 还是 &#96;take&#96;&#xff0c;其目的是代码的美观易读&#xff0c;对于程序逻辑没有丝毫影响。

[color&#61;Red]8. Named Fields[/color]



data Configuration &#61;



Configuration { username :: String,



localhost :: String,



remotehost :: String,



isguest :: Bool,



issuperuser :: Bool,



currentdir :: String,



homedir :: String,



timeconnected :: Integer



}







会转换为&#xff1a;







data Configuration &#61;



Configuration String -- user name



String -- local host



String -- remote host



Bool -- is guest?



Bool -- is super user?



String -- current directory



String -- home directory



Integer -- time connected



deriving (Eq, Show)







username :: Configuration -> String



userName (Configuration un _ _ _ _ _ _ _) &#61; un







localhost :: Configuration -> String



localHost (Configuration _ lh _ _ _ _ _ _) &#61; lh







remoteHost :: Configuration -> String



remoteHost (Configuration _ _ rh _ _ _ _ _) &#61; rh







isGuest :: Configuration -> Bool



isGuest (Configuration _ _ _ ig _ _ _ _) &#61; ig







...









hostData (Configuration {localhost&#61;lh,remotehost&#61;rh}) &#61; (lh,rh)







会转换为&#xff1a;







hostData (Configuration _ lh rh _ _ _ _ _) &#61; (lh,rh)









initCFG&#39; &#61;



Configuration



{ username&#61;"nobody",



localhost&#61;"nowhere",



remotehost&#61;"nowhere",



isguest&#61;False,



issuperuser&#61;False,



currentdir&#61;"/",



homedir&#61;"/",



timeconnected&#61;0 }







会转换为&#xff1a;







initCFG &#61; Configuration "nobody" "nowhere" "nowhere" False False "/" "/" 0







[color&#61;Blue]还有几个没有提到的&#xff0c;请参阅回帖[/color]

[ 本帖最后由 izhier 于 2009-4-19 14:29 编辑  ]





 flw 回复于&#xff1a;2009-04-09 11:36:30

关于缩进&#xff0c;既然提到了 Python&#xff0c;我觉得就不得不提到一点&#xff1a;
[color&#61;red]Haskell 不光有缩进&#xff0c;还有对齐&#xff01;[/color]

事实上&#xff0c;Haskell 的缩进和对齐这一点&#xff0c;导致了 [color&#61;red]Haskell 程序只能用空格&#xff0c;不能用 TAB。[/color]

例子如下&#xff1a;
[font&#61;新宋体]

D:/MoChou>cat ttt.hs



main &#61; do   print "hello"



print "world"







D:/MoChou>runhaskell ttt.hs



"hello"



"world"







D:/MoChou>



[/font]
上面这段代码中我使用了空格&#xff0c;而不是 TAB&#xff0c;如果用 TAB&#xff0c;而想让这个程序正确工作&#xff0c;那么就得这么写&#xff1a;
[font&#61;新宋体]

main &#61; doprint "hello"



print "world"



[/font]
这时&#xff0c;问题出现了&#xff1a;【你必须将 tab 键的宽度设置为 8 才能正常阅读此代码&#xff01;】
如果不是 8 而是 4&#xff0c;就会看到这个效果&#xff1a;
[font&#61;新宋体]

main &#61; do   print "hello"



print "world"



[/font]
而众所周知的是&#xff0c;TAB 宽度是 8 已经用的人越来越少了&#xff0c;现在流行的是 4&#xff0c;
而 Haskell 程序员经常用 2。

综上所述&#xff1a;Haskell 用户应该之用空格做缩进和对齐。
如果这个程序员正巧还在用 Python&#xff0c;那么他必须要在 Python 社区&#xff08;或公司团队中&#xff09;提倡空格抵制 TAB&#xff0c;
否则他将不得不面临为这两种语言选择两款不同的编辑器&#xff0c;或者不同的 profile 才行。

虽然像 vim 或者 emacs 这样的超级编辑器是可以为不同的语言采用不同的设置的&#xff0c;
但是许多其它的编辑器并不具备这样的功能。

[ 本帖最后由 flw 于 2009-4-9 12:54 编辑  ]




 flw 回复于&#xff1a;2009-04-09 11:41:24

其实 -> 也是语法糖。a -> b 和 【data FunctionTakeTypeASpawnTypeB a b】是一个意思。只不过很显然第一种写法更方便&#xff0c;更直观。

:i (->)




 flw 回复于&#xff1a;2009-04-09 11:48:19

还有&#xff0c;元组也是语法糖。

我一开始看到了二元组、三元组、四元组、N 元组&#xff0c;
还以为把一堆量用括号括起来、中间用逗号隔开&#xff0c;这便是元组了呢&#xff0c;
后来才发现原来不是这样。

二元组是二元组&#xff0c;三元组是三元组&#xff0c;它们根本就不是同一样东西&#xff0c;
之所以我们平时写七元组八元组都没有什么问题&#xff0c;
是因为 Haskell 环境预定义了很多种元组&#xff0c;
前段时间我试图尝试这个预定义值的上限的时候&#xff0c;失败了。
但是我确实在前几年碰到过这个上限&#xff0c;是一个并不太大的值。
也许是由于 GHC 6.10 增强了也不一定。

补充一下&#xff1a;刚才我在我的 WinHugs 上测试了一下&#xff0c;最多支持 99 元组。换句话说&#xff0c;并不存在“元组”这个类型&#xff0c;只存在 99 个 n 元组类型&#xff08;1 < n < 100&#xff09;
Version: WinHugs Sep 2006

[ 本帖最后由 flw 于 2009-4-9 11:51 编辑  ]




 izhier 回复于&#xff1a;2009-04-09 11:51:14

想问一下&#xff0c;在 List Comprehensions 中

[ fm x | x <- aList, ff x]
这样的怎么转化
难道是&#xff1a;
[ fm x | x <- aList , ff x]
&#61;>
let ok x &#61; if ff x
             then [fm x]
             else []
in concatMap ok aList

[ 本帖最后由 izhier 于 2009-4-9 11:56 编辑  ]




 roy_hu 回复于&#xff1a;2009-04-09 12:36:14

引用&#xff1a;原帖由 flw  于 2009-4-9 11:48 发表 [url&#61;http://bbs2.chinaunix.net/redirect.php?goto&#61;findpost&pid&#61;10358126&ptid&#61;1425290]
还有&#xff0c;元组也是语法糖。

我一开始看到了二元组、三元组、四元组、N 元组&#xff0c;
还以为把一堆量用括号括起来、中间用逗号隔开&#xff0c;这便是元组了呢&#xff0c;
后来才发现原来不是这样。

二元组是二元组&#xff0c;三元组是三元组&#xff0c; ... 


ghc-6.10.1支持的更少&#xff1a;
[indent]*Main> (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,3
8,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,7
5,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100)

:1:0:                                                                                              
    A 100-tuple is too large for GHC
      (max size is 62)
      Workaround: use nested tuples or define a data type[/indent]
但是ghc-6.10.2的[url&#61;http://www.haskell.org/ghc/docs/latest/html /users_guide/bugs-and-infelicities.html]user&#39;s guide里面说 Tuples are currently limited to size 100.




 roy_hu 回复于&#xff1a;2009-04-09 12:40:35

引用&#xff1a;原帖由 izhier  于 2009-4-9 11:51 发表 [url&#61;http://bbs2.chinaunix.net/redirect.php?goto&#61;findpost&pid&#61;10358144&ptid&#61;1425290]
想问一下&#xff0c;在 List Comprehensions 中

[ fm x | x  



翻译成Monad&#xff1a;
do
  x <- aList
  guard (ff x)
  return $ fm x




 flw 回复于&#xff1a;2009-04-09 12:43:02

是这样的&#xff1a;

foo &#61; [ fm x | x <- aList , ff x]




变成

foo &#61; do



x <- aList



if ff x



then return (fm x)



else fail "no message"





嗯&#xff0c;刚才看了楼上 roy_hu 兄的回复&#xff0c;
觉得用 guard 比用 if 更合适一些&#xff0c;
因为列表同时也是 MonadPlus 的实例。

[ 本帖最后由 flw 于 2009-4-9 12:57 编辑  ]

http://www.chinaunix.net/jh/142/1425290.html



推荐阅读
  • 本文详细介绍了如何在Linux系统中搭建51单片机的开发与编程环境,重点讲解了使用Makefile进行项目管理的方法。首先,文章指导读者安装SDCC(Small Device C Compiler),这是一个专为小型设备设计的C语言编译器,适合用于51单片机的开发。随后,通过具体的实例演示了如何配置Makefile文件,以实现代码的自动化编译与链接过程,从而提高开发效率。此外,还提供了常见问题的解决方案及优化建议,帮助开发者快速上手并解决实际开发中可能遇到的技术难题。 ... [详细]
  • Go语言实现Redis客户端与服务器的交互机制深入解析
    在前文对Godis v1.0版本的基础功能进行了详细介绍后,本文将重点探讨如何实现客户端与服务器之间的交互机制。通过具体代码实现,使客户端与服务器能够顺利通信,赋予项目实际运行的能力。本文将详细解析Go语言在实现这一过程中的关键技术和实现细节,帮助读者深入了解Redis客户端与服务器的交互原理。 ... [详细]
  • 掌握DSP必备的56个核心问题,我已经将其收藏以备不时之需! ... [详细]
  • 在进行网络编程时,准确获取本地主机的IP地址是一项基本但重要的任务。Winsock作为20世纪90年代初由Microsoft与多家公司共同制定的Windows平台网络编程接口,为开发者提供了一套高效且易用的工具。通过Winsock,开发者可以轻松实现网络通信功能,并准确获取本地主机的IP地址,从而确保应用程序在网络环境中的稳定运行。此外,了解Winsock的工作原理及其API函数的使用方法,有助于提高开发效率和代码质量。 ... [详细]
  • 深入解析 C 语言与 C++ 之间的差异及关联
    深入解析 C 语言与 C++ 之间的差异及关联 ... [详细]
  • 本文深入探讨了 Python Watchdog 库的使用方法和应用场景。通过详细的代码示例,展示了如何利用 Watchdog 监控文件系统的变化,包括文件的创建、修改和删除等操作。文章不仅介绍了 Watchdog 的基本功能,还探讨了其在实际项目中的高级应用,如日志监控和自动化任务触发。读者将能够全面了解 Watchdog 的工作原理及其在不同场景下的应用技巧。 ... [详细]
  • 深入RTOS实践,面对原子操作提问竟感困惑
    在实时操作系统(RTOS)的实践中,尽管已经积累了丰富的经验,但在面对原子操作的具体问题时,仍感到困惑。本文将深入探讨RTOS中的原子操作机制,分析其在多任务环境下的重要性和实现方式,并结合实际案例解析常见的问题及解决方案,帮助读者更好地理解和应用这一关键技术。 ... [详细]
  • 开发心得:深入探讨Servlet、Dubbo与MyBatis中的责任链模式应用
    开发心得:深入探讨Servlet、Dubbo与MyBatis中的责任链模式应用 ... [详细]
  • 本文详细介绍了使用响应文件在静默模式下安装和配置Oracle 11g的方法。硬件要求包括:内存至少1GB,具体可通过命令`grep -i memtotal /proc/meminfo`进行检查。此外,还提供了详细的步骤和注意事项,确保安装过程顺利进行。 ... [详细]
  • C++ 进阶:类的内存布局与虚函数类的实现细节
    C++ 进阶:类的内存布局与虚函数类的实现细节 ... [详细]
  • 深入解析Python中的循环双向链表数据结构
    本文详细探讨了Python中循环双向链表的数据结构,包括其定义、特点及应用场景。文章首先介绍了循环双向链表的基本概念,随后深入分析了其核心操作,如节点的插入、删除和遍历等。最后,通过具体的Python代码示例,展示了如何高效地实现这些操作,帮助读者全面理解并掌握这一重要数据结构。 ... [详细]
  • 【前端开发】深入探讨 RequireJS 与性能优化策略
    随着前端技术的迅速发展,RequireJS虽然不再像以往那样吸引关注,但其在模块化加载方面的优势仍然值得深入探讨。本文将详细介绍RequireJS的基本概念及其作为模块加载工具的核心功能,并重点分析其性能优化策略,帮助开发者更好地理解和应用这一工具,提升前端项目的加载速度和整体性能。 ... [详细]
  • ESP32 IRAM 内存优化策略与实践总结
    本文总结了针对ESP32 IRAM内存溢出问题的优化策略与实践经验。通过详细分析ESP32的内存结构和IRAM分配机制,提出了一系列有效的解决方案,包括代码优化、内存管理技巧和编译器配置调整,旨在帮助开发者有效解决`.espressif/tools/xtensa-esp32-elf/esp-2`等类似错误,提升系统性能和稳定性。 ... [详细]
  • Java 9 中 SafeVarargs 注释的使用与示例解析 ... [详细]
  • 如何利用Apache与Nginx高效实现动静态内容分离
    如何利用Apache与Nginx高效实现动静态内容分离 ... [详细]
author-avatar
禾漾啊
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有