编程C,C ++,Java,PHP,Ruby,图灵,VB
计算机科学加拿大 
编程C,C ++,Java,PHP,Ruby,图灵,VB  

用户名:   Password: 
 登记登记   
 [-tut]更温和的介绍,有图片! (新的!)
指数 -> 编程,一般编程 -> 功能规划
查看上3d中奖规则主题 可打印的版本下载主题订阅本主题私人信息刷新页面 查看下3d中奖规则主题
作者 信息
WTD.




邮政发布: 2004年12月23日11:26 PM  帖子主题:[-tut]温和的介绍,带图片! (新的!)

这是在Compsci.ca发布的教程的重新发布。随意问的问题。 :)

免责声明

这是另3d中奖规则尝试将功能规划的想法带到这里的群众,以及寻找能够轻松而有趣的方法的实验。

您的反馈与评估我的进展的手段也是好的。

你为什么要关心?

功能规划从根本上是一种非常不同的思考编程方式。毕竟,我们可以学习多种语言并在背上拍拍自己,但如果唯一的真正差异是句法,那么我们并没有真正受到挑战。

我需要什么?

您需要3d中奖规则Haskell解释器或编译器。对于学习目的,拥抱Haskell翻译员很好。

您可以从: http://www.haskell.org/hugs/

它尽可能轻松地安装任何其他Windows程序,并且将在“开始”菜单下创建条目:开始 - > Programs -> Hugs98.

如果您正在运行Windows 98或我,则可能是为了重新启动计算机,只是为了确保安装程序生效的所有内容。 Windows 2000和XP非常擅长立即应用更改。

哦,你想要3d中奖规则很好的文本编辑器。我建议 textpad. 与之 syntax coloring file. 方向 有关安装语法文件可用。

快速地看着拥抱

开始 -> Programs -> Hugs98 -> Nov2003 ->拥抱(98模式)

screen.width-200)this.width = (screen.width-200)" onclick="javascript:window.open('http://familygeek.com/haskell/hugs.png','','scrollbars=1,toolbar=0,resizable=1,menubar=0,directories=0,status=0')" alt="发布图像,可能已经减少了大小。点击图片以全屏观看。" title="发布图像,可能已经减少了大小。点击图片以全屏观看。" />

因此,在拥抱的启动时,我们有一些ASCII艺术,版权信息,一些基本的使用提示和提示。这是3d中奖规则很好的开始。

我们能用这怎么办?

好吧,我们可以评估表达式并查看结果。

什么是表达式?

表达式是一点点代码,它需要3d中奖规则或多个值并为您提供3d中奖规则新值。

考虑这个非常简单的例子。

screen.width-200)this.width = (screen.width-200)" onclick="javascript:window.open('http://familygeek.com/haskell/hugs2.png','','scrollbars=1,toolbar=0,resizable=1,menubar=0,directories=0,status=0')" alt="发布图像,可能已经减少了大小。点击图片以全屏观看。" title="发布图像,可能已经减少了大小。点击图片以全屏观看。" />

继续

但真的,我们可以整天做基本数学,并从我们的头骨中无聊,所以让我们看看我们可以在哪里建造更复杂的东西。

源文件只是包含代码的文本文件。我们使用的扩展是“.hs”。

那么,我们的源文件将包含什么?3d中奖规则简单的Hello World计划。

代码:
模块主要在哪里

主要的 = Putstrln."Hello, world!"


我们有什么在这里?

嗯,首先,我们必须处理Haskell代码组织成模块的事实。模块允许我们在其他程序中轻松重用代码,并且它们允许实际语言本身相对简单。文件的名称应匹配模块的名称。这里的模块被命名为“main”。

接下来我们拥有“主要”功能,活动中心,如许多其他编程语言。鉴于Haskell侧重于函数,易于创建此功能的易于创建此功能。

代码:
Putstrln."Hello, world!"


在这里,我们只需使用Putstrln函数在自己的行上将字符串打印到屏幕上。类似的PUTSTR函数是相同的,但不会自动跳到新行。

screen.width-200)this.width = (screen.width-200)" onclick="javascript:window.open('http://familygeek.com/haskell/hugs3.png','','scrollbars=1,toolbar=0,resizable=1,menubar=0,directories=0,status=0')" alt="发布图像,可能已经减少了大小。点击图片以全屏观看。" title="发布图像,可能已经减少了大小。点击图片以全屏观看。" />

测试代码

那么,我们如何在此文件中运行代码?

嗯,打开您的Trusty命令提示符窗口和“CD”到保存Main.hs文件的目录。

一旦你在那里,只需打字“拥抱”并击中Enter才能开始拥抱。我们再次回到:

screen.width-200)this.width = (screen.width-200)" onclick="javascript:window.open('http://familygeek.com/haskell/hugs.png','','scrollbars=1,toolbar=0,resizable=1,menubar=0,directories=0,status=0')" alt="发布图像,可能已经减少了大小。点击图片以全屏观看。" title="发布图像,可能已经减少了大小。点击图片以全屏观看。" />

要加载“主”模块,我们只是:

代码:
序幕> :load Main
主要的>


提示已更改为指示我们现在在主模块中,而不是前置模块。

并运行主要功能:

代码:
主要的> main
你好,world!

主要的>


所以,我们看到了一点点哈斯克尔

它是可怕的吗?

如果你说是的,那就不错。新事物可能是可怕的。你会克服它。

但是,真正的问题是:我们从哪里开始?

好吧,由于Haskell是一种功能性编程语言,我认为看一些更多功能可能很好。

在你好,世界上扩展

任何3d中奖规则甚至熟悉我的其他教程的人都将认识到以简单的Hello World计划开始的模式,然后扩展它。

所以,让我们创建3d中奖规则函数“问候”,它拿3d中奖规则名字并迎接那个人。

我们的主要.hs看起来像:

代码:
模块主要在哪里

主要的 = Putstrln."Hello, world!"


现在我们要扩展它:

代码:
模块主要在哪里

主要的= greet "Bob"

迎接名称= putstrln("Hello, " ++ name ++ "!")


当然,如果我们想要问候字符串怎么办?

代码:
模块主要在哪里

主要的= greet "Bob"

迎接名称= putstrln(greeting name)

问候name = "Hello, " ++ name ++ "!"


整理代码 - Haskell技巧

默认情况下,Haskell默认情况下,程序中使用的数据类型,但是对于文档目的,我们可以明确指定函数使用和返回的类型。

这样做,我们为主要写3d中奖规则类型的签名。 “主要”函数是3d中奖规则IO动作,并返回最接近的东西,你可以进入Haskell,所以:

代码:
模块主要在哪里

主要的:: IO ()
主要的= greet "Bob"

迎接名称= putstrln(greeting name)

问候name = "Hello, " ++ name ++ "!"


双色冒号分离函数的名称及其签名。

继续,我们为“问候”和“问候”功能生成签名。

代码:
模块主要在哪里

主要的:: IO ()
主要的= greet "Bob"

迎接:: String -> IO ()
迎接名称= putstrln(greeting name)

问候:: String -> String
问候name = "Hello, " ++ name ++ "!"


这些签名正在说,“问候将字符串作为参数呈现,并执行IO操作,”,“问候”将3d中奖规则字符串作为参数返回另3d中奖规则字符串。“

代码:
迎接名称= putstrln(greeting name)


Here we use parentheses because otherwise this would be seen as putStrLn taking two arguments, "greeting" and "名称". Since putStrLn only takes one argument, this would clearly be erroneous.

但括号会变得烦人,所以我们有$ operator。从本质上讲,$运算符在右侧取值,并将其赋予左侧的功能。所以,现在我们的问候功能看起来像:

代码:
迎接名称= putstrln$ greeting name


所以,我们的代码现在如下所示:

代码:
模块主要在哪里

主要的:: IO ()
主要的= greet "Bob"

迎接:: String -> IO ()
迎接名称= putstrln$ greeting name

问候:: String -> String
问候name = "Hello, " ++ name ++ "!"


输入以及输出

所有这些问候都不好很好,除非我们也可以从用户输入,找出他们的名字。

IO操作不太喜欢其他功能。按顺序将它们“链接在一起,我们使用关键字”do“。

代码:
模块主要在哪里

主要的:: IO ()
主要的= do putstr"You are? "
          name <- getLine
          greet name

迎接:: String -> IO ()
迎接名称= putstrln$ greeting name

问候:: String -> String
问候name = "Hello, " ++ name ++ "!"


可能是最紧张的令人责任的变化是使用缩进。 Haskell使用称为“布局”的内容,因此不需要半冒号和括号。它们可用:

代码:
主要的= do {putstr"You are? ";
名称 <- getLine;
迎接name }


当然,“布局”方法如此友好,它可以愚蠢地使用牙套和半冒号。

第二个新的语法是:

代码:
名称 <- getLine


GetLine的返回是3d中奖规则字符串,但是3d中奖规则“受污染的”字符串,无法立即使用。使用<- syntax, "名称" is a plain old string we can use elsewhere.

条件

当给出问候函数的名字是“Haskell”的时候,问候语是“嘿,哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇

代码:
模块主要在哪里

主要的:: IO ()
主要的= do putstr"You are? "
          name <- getLine
          greet name

迎接:: String -> IO ()
迎接名称= putstrln$ greeting name

问候:: String -> String
问候name =
  if name == "Haskell"
    then "Hey, whadda ya know? 这是3d中奖规则节目!"
    else "Hello, " ++ name ++ "!"


这应该对具有其他语言基本经验的程序员相当直接。此外,我们再次使用“布局”表示条件的结构。

案例表达式

让我们说我们希望我们的计划迎接“Matz”,“你做了3d中奖规则很好的语言。”仅使用“if”:

代码:
模块主要在哪里

主要的:: IO ()
主要的= do putstr"You are? "
          name <- getLine
          greet name

迎接:: String -> IO ()
迎接名称= putstrln$ greeting name

问候:: String -> String
问候name =
  if name == "Haskell"
    then "Hey, whadda ya know? 这是3d中奖规则节目!"
    else if name == "Matz"
           then ""
           else "Hello, " ++ name ++ "!"


哇,那是丑陋的。幸运的是,我们有表达式的表达式应该看起来熟悉程序员。

代码:
模块主要在哪里

主要的:: IO ()
主要的= do putstr"You are? "
          name <- getLine
          greet name

迎接:: String -> IO ()
迎接名称= putstrln$ greeting name

问候:: String -> String
问候name =
  case name of
    "Haskell" -> "Hey, whadda ya know? 这是3d中奖规则节目!"
    "Matz"    -> ""
    otherwise -> "Hello, " ++ name ++ "!"


与“如果”一样,我们使用布局。

超载功能

当然,我们可以通过重载问候函数来更干净地完成这一点。

代码:
模块主要在哪里

主要的:: IO ()
主要的= do putstr"You are? "
          name <- getLine
          greet name

迎接:: String -> IO ()
迎接名称= putstrln$ greeting name

问候:: String -> String
问候"Haskell" = "Hey, whadda ya know? 这是3d中奖规则节目!"
问候"Matz"    = ""
问候name      = "Hello, " ++ name ++ "!"


循环

此时,您可能会询问Haskell如何处理循环,因为这对于程序员在其他语言中了解了3d中奖规则非常基本的东西。

提供了循环的特殊语法。所有循环都通过递归来实现,其中函数调用自身。

代码:
模块主要在哪里

主要的:: IO ()
主要的= do putstr"You are? "
          name <- getLine
          if name == "quit"
            then return ()
            else do greet name
                    main

迎接:: String -> IO ()
迎接名称= putstrln$ greeting name

问候:: String -> String
问候"Haskell" = "Hey, whadda ya know? 这是3d中奖规则节目!"
问候"Matz"    = ""
问候name      = "Hello, " ++ name ++ "!"


可能会出现一些问题:

  • 代码:
    返回()


    “回归”做什么?这基本上将()转换为IO(),这是返回我们的主要功能的返回。
  • 为什么“do”在“如果”表达式中重复? “如果”基本上中断我们创建的表达链。要启动另3d中奖规则“链”,我们需要再次使用“do”。


清单

所以,我们可以迎接一些人。当然,如果我们希望能够获得我们迎接的人列表怎么办?

好吧,我们需要3d中奖规则清单。 Haskell中的列表可以包含任意数量的值,只要它们都是相同的类型。最基本的列表是空列表:

代码:
[]


3d中奖规则小小的名称可能看起来像:

代码:
["Bob", "John"]


在其他编程语言中处理此类结构的任何事情,我们经常使用术语“阵列”,应该立即引起核心环。当然,我们已经涵盖了这一点。 Haskell没有明确的循环语法,而是递归。因此,解决方案是找到以递归方式定义列表的方法。

值得庆幸的是,Haskell列表是自然递归的。 :操作符将元素添加到列表的开头。我们的名称列表可以如下所示:

代码:
"Bob" : "John" : []


让我们在3d中奖规则简单的例子中看待这一点。简单的范围函数应该从开始到结束时创建3d中奖规则数字列表。

代码:
范围S e =如果是> e
              then []
              else s : range (s + 1) e


直到我们打破样本使用它,这可能看起来相当密切。

代码:
范围1 5.
1 : range 2 5
1 : 2 : range 3 5
1 : 2 : 3 : range 4 5
1 : 2 : 3 : 4 : range 5 5
1 : 2 : 3 : 4 : 5 : range 6 5
1 : 2 : 3 : 4 : 5 : []
1 : 2 : 3 : 4 : [5]
1 : 2 : 3 : [4, 5]
1 : 2 : [3, 4, 5]
1 : [2, 3, 4, 5]
[1,2,3,4,5]


看到有两个参数的函数指出了关于Haskell的有趣事实。对函数的参数只是空格分隔,而不是逗号,而不是逗号,如许多其他编程语言中。

所以,我们也可以跳进。

代码:
模块主要在哪里

主要的:: IO [String]
主要的= do putstr"You are? "
          name <- getLine
          if name == "quit"
            then return []
            else do greet name
                    nextRun <- main
                    return $ name : nextRun


迎接:: String -> IO ()
迎接名称= putstrln$ greeting name

问候:: String -> String
问候"Haskell" = "Hey, whadda ya know? 这是3d中奖规则节目!"
问候"Matz"    = ""
问候name      = "Hello, " ++ name ++ "!"


打破它

一如既往地,将3d中奖规则大型复杂程序分为小,可理解的组件对理解至关重要。

代码:
主要的:: IO [String]


我们的新签名表示它返回字符串列表。当然,它仍然是“污染”。

代码:
返回 []


如前所述,如果用户进入“quit”,则我们停止“循环”。但是,我们返回3d中奖规则空名单,就像我们在范围内所做的那样。

代码:
nextrun.<- main


我们无法直接使用Main,因为它返回IO污染列表。相反,我们首先提取该列表。

代码:
返回$名称: nextRun


在这里,我们将当前名称添加到通过再次运行主函数生成的名称列表中,然后“返回”该列表。它看起来很奇怪,但上次运行的主要功能是最后完成。

另3d中奖规则功能

由于这变得相当复杂,也许我们应该将其分成3d中奖规则单独的功能。

代码:
模块主要在哪里

主要的:: IO [String]
主要的 = Grentmultiple.

迎接:: String -> IO ()
迎接名称= putstrln$ greeting name

问候:: String -> String
问候"Haskell" = "Hey, whadda ya know? 这是3d中奖规则节目!"
问候"Matz"    = ""
问候name      = "Hello, " ++ name ++ "!"

问候语:: IO [String]
问候dultipre = do putstr"You are? "
                   name <- getLine
                   if name == "quit"
                     then return []
                     else do greet name
                             nextRun <- greetMultiple
                             return $ name : nextRun


另3d中奖规则

不是很大的变化,但现在我们可以用文章问候语追回。让我们介绍3d中奖规则新的函数来打印列表中的所有字符串。

代码:
打印机:: [String] -> IO ()
打印机[]     = return ()
打印机(x:xs) = do putStrLn x
                     printAll xs


在这里,我们超载了PrintAll函数,因此打印空列表只是返回()。当我想打印实际列表时,我使用模式“(x:xs)”。我们见过:之前。它在我们构建列表时使用。所以这里X是列表中的第3d中奖规则元素。列表的其余部分是“xs”,可以读取为“x”的复数。

我们的代码现在看起来像:

代码:
模块主要在哪里

主要的:: IO ()
主要的= do名字<- greetMultiple
          putStrLn "I greeted:"
          printAll names

迎接:: String -> IO ()
迎接名称= putstrln$ greeting name

问候:: String -> String
问候"Haskell" = "Hey, whadda ya know? 这是3d中奖规则节目!"
问候"Matz"    = ""
问候name      = "Hello, " ++ name ++ "!"

问候语:: IO [String]
问候dultipre = do putstr"You are? "
                   name <- getLine
                   if name == "quit"
                     then return []
                     else do greet name
                             nextRun <- greetMultiple
                             return $ name : nextRun
                             
打印机:: [String] -> IO ()
打印机[]     = return ()
打印机(x:xs) = do putStrLn x
                     printAll xs


有一种更简单的方式

将函数应用于列表中的每个元素的任务是如此常见的任务,您认为已经存在函数或功能来解决此问题。

当我们应用正常函数时,我们可以使用“地图”。让我们说我们希望在列表中加倍每个数字。

代码:
timestwo x = x * 2

地图Timestwo [1,2,3,4]


现在,当我们使用IO“动作”时,我们无法使用地图,而是我们使用MAPM_函数。

代码:
模块主要在哪里

主要的:: IO ()
主要的= do名字<- greetMultiple
          putStrLn "I greeted:"
         mapm_ putstrln名称

迎接:: String -> IO ()
迎接名称= putstrln$ greeting name

问候:: String -> String
问候"Haskell" = "Hey, whadda ya know? 这是3d中奖规则节目!"
问候"Matz"    = ""
问候name      = "Hello, " ++ name ++ "!"

问候语:: IO [String]
问候dultipre = do putstr"You are? "
                   name <- getLine
                   if name == "quit"
                     then return []
                     else do greet name
                             nextRun <- greetMultiple
                             return $ name : nextRun


不同的问候方法

现在,让我们说我们首先想要收集3d中奖规则小组的名字,然后迎接他们所有人。首先,我们需要3d中奖规则收集函数。

代码:
收集名意:: IO [String]
收集命名= do putstr"You are? "
                 name <- getLine
                 if name == "quit"
                   then return []
                   else do otherNames <- gatherNames
                           return $ name : otherNames


现在我们可以将其纳入我们的程序并使用Map来生成适当的问候语,然后通过$ $ to我们已经看到的“MapM_PUTSTRLN”的结果。

代码:
模块主要在哪里

主要的:: IO ()
主要的= do名字<- gatherNames
         MAPM_PUTSTRLN $地图问候名称

迎接:: String -> IO ()
迎接名称= putstrln$ greeting name

问候:: String -> String
问候"Haskell" = "Hey, whadda ya know? 这是3d中奖规则节目!"
问候"Matz"    = ""
问候name      = "Hello, " ++ name ++ "!"
                     
收集名意:: IO [String]
收集命名= do putstr"You are? "
                 name <- getLine
                 if name == "quit"
                   then return []
                   else do otherNames <- gatherNames
                           return $ name : otherNames


回到printall.

代码:
mapm_ putstrln名称


当然,我们可以看看这个,并认为它在使用中的丑陋而不是:

代码:
打印机names


但之前我们已经看到,PrintAll的定义增加了相当多的不必要的代码。所以,让我们重新定义打印机。

代码:
打印机:: [String] -> IO ()
打印名称名称= mapm_ putstrln名称


好多了。但是,我们可以进一步改进。在haskell,如果我们有3d中奖规则函数,它需要两个参数,并且只给它3d中奖规则参数中的3d中奖规则,我们得到了另3d中奖规则函数,它采用了最终参数。

这被称为“部分应用程序”。函数的部分应用程序允许我们根据现有功能轻松创建新功能。 PrintAll函数可以重写为:

代码:
打印机:: [String] -> IO ()
打印机= mapM_ putStrLn


同样我们可以生成如此如此的问候语:

代码:
问候:: [String] -> [String]
问候= map greeting


现在,我们的代码看起来像:

代码:
模块主要在哪里

主要的:: IO ()
主要的= do名字<- gatherNames
         打印符号$问候名称

迎接:: String -> IO ()
迎接名称= putstrln$ greeting name

问候:: String -> String
问候"Haskell" = "Hey, whadda ya know? 这是3d中奖规则节目!"
问候"Matz"    = ""
问候name      = "Hello, " ++ name ++ "!"

问候语:: IO [String]
问候dultipre = do putstr"You are? "
                   name <- getLine
                   if name == "quit"
                     then return []
                     else do greet name
                             nextRun <- greetMultiple
                             return $ name : nextRun
                     
收集名意:: IO [String]
收集命名= do putstr"You are? "
                 name <- getLine
                 if name == "quit"
                   then return []
                   else do otherNames <- gatherNames
                           return $ name : otherNames
                           
打印机:: [String] -> IO ()
打印机= mapM_ putStrLn

问候:: [String] -> [String]
问候= map greeting


结合数据

在许多情况下,数据并不像某人的名字那么简单。我们经常希望将不同的数据分组成3d中奖规则单位。在Haskell,我们通过元组完成他的通过元组。

所以,有3d中奖规则名字,让我们说我们也想存储3d中奖规则年龄,所以我们的问候函数可以根据年龄提出问候。那个示例元组可能是:

代码:
("Bob", 49)


但是,首先,我们需要能够从用户读取整数。由于读入的一切都是字符串的形式,因此我们需要一种方法来从字符串中提取整数。 “读取”功能步骤。现在,读取返回沿线的内容:

代码:
[(Int, String)]


因此,我们需要从数组中获取第3d中奖规则元素,以及来自元组的第3d中奖规则项目。这 !!操作员和FST功能将非常好。

因此,基本的Getage函数可能如下所示:

代码:
养育:: IO Integer         
GetAge = Do Putstr"And you're how old? "
            input <- getLine
           返回$ fst $读取输入!! 0.


这只是3d中奖规则问题,这是3d中奖规则很大的问题。如果有人给你不好的投入怎么办?好吧,然后读取会给我们提供空名单,这使得“读取输入!! 0”导致错误。

我们需要一种方法来避免首先出错。我们可以通过添加条件表达式来检查,该表达式检查列表是否为空。当然,如果是,我们可能会告诉用户我们没有获得年龄,并再次询问他们。递归将在这里为我们服务。

代码:
养育:: IO Int
GetAge = Do Putstr"And you're how old? "
            input <- getLine
           让解析=读取输入
            if parsed == []
              then do putStrLn "对不起,你能重复一遍吗?"
                      getAge
             否则返回$ fst $ sarsed !! 0.


再次回来

我们希望不仅可以获得名字,而且还想要他们的年龄。在我们之前有3d中奖规则收集命令的位置,让我们用Grooginfo函数替换它。

代码:
灰色的Info.:: IO [(String, Int)]
灰色的Info =做Putstr"You are? "
                name <- getLine
                if name == "quit"
                  then return []
                  else do age <- getAge
                          let info = (name,age)
                          otherInfo <- gatherInfo
                          return $ info : otherInfo


基本形式看起来几乎与我们定义的其他递归函数相似。

现在,即使我们在这里有3d中奖规则非常不同类型的数据,我们可以从地图和FST获取每条信息中的字符串。

代码:
模块主要在哪里

主要的:: IO ()
主要的=做信息<- gatherInfo
         让名称=地图FST信息
         打印符号$问候名称

问候:: String -> String
问候"Haskell" = "Hey, whadda ya know? 这是3d中奖规则节目!"
问候"Matz"    = ""
问候name      = "Hello, " ++ name ++ "!"
                           
打印机:: [String] -> IO ()
打印机= mapM_ putStrLn

问候:: [String] -> [String]
问候= map greeting
         
养育:: IO Int
GetAge = Do Putstr"And you're how old? "
            input <- getLine
           让解析=读取输入
            if parsed == []
              then do putStrLn "对不起,你能重复一遍吗?"
                      getAge
             否则返回$ fst $ sarsed !! 0.

灰色的Info.:: IO [(String, Int)]
灰色的Info =做Putstr"You are? "
                name <- getLine
                if name == "quit"
                  then return []
                  else do age <- getAge
                          let info = (name,age)
                          otherInfo <- gatherInfo
                          return $ info : otherInfo


用额外信息做点什么

现在我们对我们问候的每个人都有名字和年龄信息,我们仍然可以迎接旧方式的人,但这似乎缺少首先拥有额外信息的观点。因此,我们希望根据年龄和名称获得不同的问候语。

所以,我们首先要重复问候功能。我们的旧问候功能看起来像:

代码:
问候:: String -> String
问候"Haskell" = "Hey, whadda ya know? 这是3d中奖规则节目!"
问候"Matz"    = ""
问候name      = "Hello, " ++ name ++ "!"


我们意识到的第一件事将不得不改变是这个功能的签名。

代码:
问候:: (String,Int) -> String


现在,为了其余的,如果年龄不到十二,我们将回答:“你的父母知道你在哪里,<name>?“如果年龄大于八十,我们将回答:”孩子们知道你在哪里,<name>?“否则,我们将使用我们在先前的问候函数中应用的相同规则。

为此,我们将使用“警卫”来定义这些不同条件的多个版本。语法应该相当明显。

代码:
问候:: (String,Int) -> String
问候(name,age)
  | age < 12          = "你的父母知道你在哪里,"  ++ name ++ "?"
  | age > 80          = "你的孩子知道你在哪里," ++ name ++ "?"
  | name == "Haskell" = "Hey, whadda ya know? 这是3d中奖规则节目!"
  | name == "Matz"    = ""
  | otherwise         = "Hello, " ++ name ++ "!"


所以,我们的整个计划现在:

代码:
模块主要在哪里

主要的:: IO ()
主要的=做信息<- gatherInfo
         打印$ $问候信息
         

迎接:: (String,Int) -> IO ()
迎接名称= putstrln$ greeting name
                     
收集名意:: IO [String]
收集命名= do putstr"You are? "
                 name <- getLine
                 if name == "quit"
                   then return []
                   else do otherNames <- gatherNames
                           return $ name : otherNames
                           
打印机:: [String] -> IO ()
打印机= mapM_ putStrLn

问候:: [(String,Int)] -> [String]
问候= map greeting
         
养育:: IO Int
GetAge = Do Putstr"And you're how old? "
            input <- getLine
           让解析=读取输入
            if parsed == []
              then do putStrLn "对不起,你能重复一遍吗?"
                      getAge
             否则返回$ fst $ sarsed !! 0.

灰色的Info.:: IO [(String, Int)]
灰色的Info =做Putstr"You are? "
                name <- getLine
                if name == "quit"
                  then return []
                  else do age <- getAge
                          let info = (name,age)
                          otherInfo <- gatherInfo
                          return $ info : otherInfo

问候:: (String,Int) -> String
问候(name,age)
  | age < 12          = "你的父母知道你在哪里,"  ++ name ++ "?"
  | age > 80          = "你的孩子知道你在哪里," ++ name ++ "?"
  | name == "Haskell" = "Hey, whadda ya know? 这是3d中奖规则节目!"
  | name == "Matz"    = ""
  | otherwise         = "Hello, " ++ name ++ "!"


模块

因此,我们已经看到了输入,输出,字符串,函数,条件,列表,元组和一些非常方便的功能,如映射和MAPM_。下一步是什么?

好吧,看着上面的程序,大多数它处理问候人,然后3d中奖规则孤独的功能是一切都发生的主要功能。如果我想使用与另3d中奖规则程序中的问候语相关的函数,但我想要3d中奖规则不同的主要函数怎么办?

好吧,然后我需要将所有这些功能放入自己的模块中。让我们称之为新的模块问候语。当然,它将位于文件问候语中。

代码:
模块问候在哪里

迎接:: (String,Int) -> IO ()
迎接名称= putstrln$ greeting name
                     
收集名意:: IO [String]
收集命名= do putstr"You are? "
                 name <- getLine
                 if name == "quit"
                   then return []
                   else do otherNames <- gatherNames
                           return $ name : otherNames
                           
打印机:: [String] -> IO ()
打印机= mapM_ putStrLn

问候:: [(String,Int)] -> [String]
问候= map greeting
         
养育:: IO Int
GetAge = Do Putstr"And you're how old? "
            input <- getLine
           让解析=读取输入
            if parsed == []
              then do putStrLn "对不起,你能重复一遍吗?"
                      getAge
             否则返回$ fst $ sarsed !! 0.

灰色的Info.:: IO [(String, Int)]
灰色的Info =做Putstr"You are? "
                name <- getLine
                if name == "quit"
                  then return []
                  else do age <- getAge
                          let info = (name,age)
                          otherInfo <- gatherInfo
                          return $ info : otherInfo

问候:: (String,Int) -> String
问候(name,age)
  | age < 12          = "你的父母知道你在哪里,"  ++ name ++ "?"
  | age > 80          = "你的孩子知道你在哪里," ++ name ++ "?"
  | name == "Haskell" = "Hey, whadda ya know? 这是3d中奖规则节目!"
  | name == "Matz"    = ""
  | otherwise         = "Hello, " ++ name ++ "!"


没有我们的主模块简而言之:

代码:
模块主要在哪里

进口问候语

主要的:: IO ()
主要的=做信息<- gatherInfo
         打印$ $问候信息


当然,如果你希望它是明确的,那么来自你使用的函数来自的,你可以预先添加模块的名称。

代码:
模块主要在哪里

进口问候语

主要的:: IO ()
主要的=做信息< - 问候.gatherinfo.
         迎接.printall $ redgring.greetings信息


这可以通过使用“限定”导入修改器来Encorcence。

代码:
模块主要在哪里

进口合格的问候语

主要的:: IO ()
主要的=做信息< - 问候.gatherinfo.
         迎接.printall $ redgring.greetings信息


我们可以限制我们导入的功能。

代码:
模块主要在哪里

进口问候语(GrayInfo,Printall,问候)

主要的:: IO ()
主要的=做信息<- gatherInfo
         打印$ $问候信息


介绍我们自己的数据类型

当然,此时,我们已经使用了元组形式的新数据类型。但是,我们指望能够认识到由字符串和整数组成的元组是3d中奖规则人。

哈斯克尔通过引入新数据类型使我们能够更具表现力。在这种情况下,它真的很简单。

代码:
数据personinfo = person string int


这引入了一种名为personInfo的新类型,其中单个构造函数带有3d中奖规则字符串和int。因此,让我们首先重新定义问候函数来利用这种新数据类型。

代码:
问候:: PersonInfo -> String
问候(Person name age)
  | age < 12          = "你的父母知道你在哪里,"  ++ name ++ "?"
  | age > 80          = "你的孩子知道你在哪里," ++ name ++ "?"
  | name == "Haskell" = "Hey, whadda ya know? 这是3d中奖规则节目!"
  | name == "Matz"    = ""
  | otherwise         = "Hello, " ++ name ++ "!"


并且,修改我们的其余代码来使用此新数据类型,我们最终结束:

代码:
模块问候在哪里
         
数据personinfo = person string int         
         
迎接:: PersonInfo -> IO ()
问候p = putstrln $问候p
                           
打印机:: [String] -> IO ()
打印机= mapM_ putStrLn

问候:: [PersonInfo] -> [String]
问候= map greeting
         
养育:: IO Int
GetAge = Do Putstr"And you're how old? "
            input <- getLine
           让解析=读取输入
            if parsed == []
              then do putStrLn "对不起,你能重复一遍吗?"
                      getAge
             否则返回$ fst $ sarsed !! 0.

灰色的Info.:: IO [PersonInfo]
灰色的Info =做Putstr"You are? "
                name <- getLine
                if name == "quit"
                  then return []
                  else do age <- getAge
                         让信息=人名年龄
                          otherInfo <- gatherInfo
                          return $ info : otherInfo

问候:: PersonInfo -> String
问候(Person name age)
  | age < 12          = "你的父母知道你在哪里,"  ++ name ++ "?"
  | age > 80          = "你的孩子知道你在哪里," ++ name ++ "?"
  | name == "Haskell" = "Hey, whadda ya know? 这是3d中奖规则节目!"
  | name == "Matz"    = ""
  | otherwise         = "Hello, " ++ name ++ "!"


要到达这一点,我对我之前的代码进行了很少的变化。这应该表现出哈斯克尔的表现力。

问候其他东西

现在,我们已经定义了一组用于问候3d中奖规则人的功能。但是,人们不是我们可能想要迎接的唯一事情。例如,考虑我们想迎接狗的情况。出于我们的程序目的,狗将由其名称,构建和颜色描述。根据这些事情,我们将制定3d中奖规则问候。

不过,第一件事首先。让我们定义我们需要的数据类型。

代码:
数据构建=瘦身|中等|胖的
数据颜色=白色|黑色|灰色|红色|棕色的
Data Doginfo =狗字符串构建颜色


在构建和颜色数据类型中,我们有一组占用的构造函数,该构造函数没有参数。这些构造函数中的任何3d中奖规则都会创建类型构建或颜色的值。这有点类似于其他语言的枚举类型或“枚举”的想法。

然后,狗构造函数使用这些数据类型。

让我们谈谈课程

出于本文档的目的,请借助您在面向对象语言中了解的类别,如C ++,Java,C#,Python,Ruby,Eiffel等。我们在讨论Haskell的课程时,我们正在谈论分类数据类型根据我们可以在它们上使用的功能。

以这种方式对数据类型进行分类的优点是,在声明函数时,我们不需要具体。考虑我目前的问候函数声明。

代码:
问候:: PersonInfo -> String


这要求参数是职人为的。鉴于此,我们不能简单地定义问候语来掌握DogInfo类型。我们想要的是根据我们是否可以迎接它们来分类数据类型。

所以,让我们创建3d中奖规则这样做的课程。

代码:
班级贺者答案
  greeting :: a -> String


这相当简单。这里“a”表示“贺卡类”中的任何类型。让我们添加一些与第3d中奖规则相关的功能。

代码:
班级贺者答案
  greeting  :: a -> String
  greetings :: [a] -> [String]
  greet     :: a -> IO ()


现在,Haskell的课程有趣的是,我们不仅可以指定这些函数的类型,而且如果我们有相关的功能,只需依赖于另3d中奖规则功能,我们可以提供默认定义。现在,当我们稍后定义问候语时,我们会自动获得其他两个。

代码:
班级贺者答案
  -- declarations
  greeting  :: a -> String
  greetings :: [a] -> [String]
  greet     :: a -> IO ()
  - 默认定义
  greetings  = map greeting
  迎接名称= putstrln$ greeting name


有一件事要注意到我第一次使用评论。任何以下内容 - 在一条线上是Haskell的评论。

实例

通过实例声明将数据类型录取到类。这是我们定义类所需功能的地方。承认人物文件数据类型进入问候类。

代码:
实例是难题的人物文件在哪里
  greeting (Person name age)
    | age < 12          = "你的父母知道你在哪里,"  ++ name ++ "?"
    | age > 80          = "你的孩子知道你在哪里," ++ name ++ "?"
    | name == "Haskell" = "Hey, whadda ya know? 这是3d中奖规则节目!"
    | name == "Matz"    = ""
    | otherwise         = "Hello, " ++ name ++ "!"


这看起来很漂亮与我们以前的问候定义相似,所以这里没有很多新的东西来学习。

所以,现在我们现有的程序看起来像:

代码:
模块问候在哪里
         
数据personinfo = person string int
  deriving (Show, Eq)

班级贺者答案
  -- declarations
  greeting  :: a -> String
  greetings :: [a] -> [String]
  greet     :: a -> IO ()
  - 默认定义
  greetings =  map greeting
  greet x   = putstrln $问候语x

实例是难题的人物文件在哪里
  greeting (Person name age)
    | age < 12          = "你的父母知道你在哪里,"  ++ name ++ "?"
    | age > 80          = "你的孩子知道你在哪里," ++ name ++ "?"
    | name == "Haskell" = "Hey, whadda ya know? 这是3d中奖规则节目!"
    | name == "Matz"    = ""
    | otherwise         = "Hello, " ++ name ++ "!"
                     
收集名意:: IO [String]
收集命名= do putstr"You are? "
                 name <- getLine
                 if name == "quit"
                   then return []
                   else do otherNames <- gatherNames
                           return $ name : otherNames
                           
打印机:: [String] -> IO ()
打印机= mapM_ putStrLn
         
养育:: IO Int
GetAge = Do Putstr"And you're how old? "
            input <- getLine
           让解析=读取输入
            if parsed == []
              then do putStrLn "对不起,你能重复一遍吗?"
                      getAge
             否则返回$ fst $ sarsed !! 0.

灰色的Info.:: IO [PersonInfo]
灰色的Info =做Putstr"You are? "
                name <- getLine
                if name == "quit"
                  then return []
                  else do age <- getAge
                         让信息=人名年龄
                          otherInfo <- gatherInfo
                          return $ info : otherInfo


当然,这些变化都没有影响我们的主要模块。

Sidetracking:展示课

所以我们看到了一类自己的设计。 Haskell 98中还有其他类。3d中奖规则有用的类是Show类,这要求定义“show”功能。那个课程看起来像:

代码:
班级显示在哪里
  show :: a -> String


这提供了3d中奖规则方便的方法来获得某种东西的字符串表示。例如,要打印int,我们将使用以下内容,因为Putstrln只能处理字符串。

代码:
Putstrln.$ show 42


或者将整数添加到字符串:

代码:
"Foo " ++ show 42


让我们考虑更具相关的情况。以前,我们已定义数据类型颜色。

代码:
数据颜色=白色|黑色|灰色|红色|棕色的


现在,在某些时候,我们可能希望实际上得到3d中奖规则包含“白色”或“红色”的字符串。我们可以通过制作彩色的3d中奖规则例子来实现这一目标。

代码:
实例显示颜色在哪里
  show White = "White"
  show Black = "Black"
  show Gray  = "Gray"
  show Red   = "Red"
  show Brown = "Brown"


似乎应该有一种更简单的方法来实现如此简单的转变。嗯,对于这样的基本类,我们可以在没有实例声明的情况下为show类的成员进行颜色。

代码:
数据颜色=白色|黑色|灰色|红色|棕色的
  deriving (Show)


当然,在这个程序的过程中,我们可能想要“红色”而不是“红色”。幸运的是,我们可以简单地在这种情况下使用地图。您看到的Haskell中的字符串只是3d中奖规则字符列表。

首先,我们必须从char模块导入tolower函数。

代码:
导入合格的字符(toLower)


然后我们可以轻松应用地图。

代码:
地图char.tolower $ show红色


回到主题:问候狗

所以,我们有3d中奖规则难看的类,要求班级成员定义问候函数,并如果我们这样做,我们会给我们一些免费功能。

代码:
班级贺者答案
  -- declarations
  greeting  :: a -> String
  greetings :: [a] -> [String]
  greet     :: a -> IO ()
  - 默认定义
  greetings  = map greeting
  迎接名称= putstrln$ greeting name


我们有几种新数据类型。

代码:
数据构建=瘦身|中等|胖的
数据颜色=白色|黑色|灰色|红色|棕色衍生(Show)
Data Doginfo =狗字符串构建颜色


我们需要的是使Doginfo成为3d中奖规则难题的实例。

代码:
实例是难题的Doginfo在哪里
  greeting (Dog _    Skinny _    ) = "那只狗几乎没有任何东西。"
  greeting (Dog _    Fat    _    ) = "What a fat dog!"
  greeting (Dog name _      color) = "What a healthy " ++
                                     (地图char.tolower $ show颜色) ++
                                     " dog.  Hello, " ++ name ++ "!"


此示例显示了Haskell的3d中奖规则重要新功能。即,对所有下划线的交易是什么?

嗯,在Haskell,在匹配模式时,您必须包含所有参数。当然,有时你只是不在乎这个论点。当我们迎接瘦或胖狗时,我们粗鲁,不关心狗的名字或颜色是什么。无论如何,我们只是要侮辱它。

当我们不关心3d中奖规则争论时,我们使用下划线。这意味着是的,那里有3d中奖规则参数,但我们不足以给它3d中奖规则名字。

最终,我有以下计划。

代码:
模块问候在哪里
         
导入合格的字符(toLower)         
         
数据personinfo = person string int

班级贺者答案
  -- declarations
  greeting  :: a -> String
  greetings :: [a] -> [String]
  greet     :: a -> IO ()
  - 默认定义
  greetings =  map greeting
  greet x   = putstrln $问候语x

实例是难题的人物文件在哪里
  greeting (Person name age)
    | age < 12          = "你的父母知道你在哪里,"  ++ name ++ "?"
    | age > 80          = "你的孩子知道你在哪里," ++ name ++ "?"
    | name == "Haskell" = "Hey, whadda ya know? 这是3d中奖规则节目!"
    | name == "Matz"    = ""
    | otherwise         = "Hello, " ++ name ++ "!"
                           
打印机:: [String] -> IO ()
打印机= mapM_ putStrLn
         
养育:: IO Int
GetAge = Do Putstr"And you're how old? "
            input <- getLine
           让解析=读取输入
            if parsed == []
              then do putStrLn "对不起,你能重复一遍吗?"
                      getAge
             否则返回$ fst $ sarsed !! 0.

灰色的Info.:: IO [PersonInfo]
灰色的Info =做Putstr"You are? "
                name <- getLine
                if name == "quit"
                  then return []
                  else do age <- getAge
                         让信息=人名年龄
                          otherInfo <- gatherInfo
                          return $ info : otherInfo

数据构建=瘦身|中等|胖的
数据颜色=白色|黑色|灰色|红色|棕色衍生(Show)
Data Doginfo =狗字符串构建颜色

实例是难题的Doginfo在哪里
  greeting (Dog _    Skinny _    ) = "那只狗几乎没有任何东西。"
  greeting (Dog _    Fat    _    ) = "What a fat dog!"
  greeting (Dog name _      color) = "What a healthy " ++
                                     (地图char.tolower $ show颜色) ++
                                     " dog.  Hello, " ++ name ++ "!"


最终结果

此时,我可以使用相同的功能迎接3d中奖规则人或一只狗,即使两者除了问候函数之外的任何共同之处。当然,他们还有什么需要分享?

代码:
迎接$人"John" 19
   greet $ Dog "Fido" Medium Brown


我们在屏幕上看到:

代码:
你好,John!
多么健康brown dog.  Hello, Fido!


汇编

此时你可能会认为这一切都很好,但这种解释方法,我们写了代码,然后测试它是繁琐的,而且没有真正适合编写3d中奖规则可以运行的程序,做它的事情,然后退出。

幸运的是,可以编写到原生代码以及解释。

我们将使用的编译器是Glorious Glasgow编译系统,或者可用于:

http://www.haskell.org/ghc/

适用于Windows的安装程序可在:

http://www.haskell.org/ghc/download_ghc_622.html#windows

要编译我们组装的程序,命令是:

代码:
迅速的>ghc -o - 纸张main -o greeter.exe


-O告诉编译器执行优化, - 拍摄告诉编译器我们实际基于此模块构建可执行文件,而且--o告诉编译器的结果可执行文件的名称。

现在,我们可以运行此程序。

代码:
迅速的> greeter


我们看到了一些相当奇怪的东西。没有什么。

我们为什么不看任何?

嗯,这是3d中奖规则与功能规划无关的小小的东西。问题是,使用GHC编译的Haskell程序不会在输入换行符之前输出任何内容。当我们问,“你是?”,我们不去3d中奖规则新行,所以没有什么可以打印到屏幕上。

修复很简单。我们需要在标准输出中刷新所有文本。为此,我们需要导入IO模块,然后在Putst的每个实例后刷新标准输出。 putstrln函数没有这个问题。

随着这表达,我们的问候模块现在看起来像:

代码:
模块问候在哪里
         
导入合格的字符(toLower) 
导入IO.
         
数据personinfo = person string int

班级贺者答案
  -- declarations
  greeting  :: a -> String
  greetings :: [a] -> [String]
  greet     :: a -> IO ()
  - 默认定义
  greetings =  map greeting
  greet x   = putstrln $问候语x

实例是难题的人物文件在哪里
  greeting (Person name age)
    | age < 12          = "你的父母知道你在哪里,"  ++ name ++ "?"
    | age > 80          = "你的孩子知道你在哪里," ++ name ++ "?"
    | name == "Haskell" = "Hey, whadda ya know? 这是3d中奖规则节目!"
    | name == "Matz"    = ""
    | otherwise         = "Hello, " ++ name ++ "!"
                           
打印机:: [String] -> IO ()
打印机= mapM_ putStrLn
         
养育:: IO Int
GetAge = Do Putstr"And you're how old? "
            hFlush stdout
            input <- getLine
           让解析=读取输入
            if parsed == []
              then do putStrLn "对不起,你能重复一遍吗?"
                      getAge
             否则返回$ fst $ sarsed !! 0.

灰色的Info.:: IO [PersonInfo]
灰色的Info =做Putstr"You are? "
                hFlush stdout
                name <- getLine
                if name == "quit"
                  then return []
                  else do age <- getAge
                         让信息=人名年龄
                          otherInfo <- gatherInfo
                          return $ info : otherInfo

数据构建=瘦身|中等|胖的
数据颜色=白色|黑色|灰色|红色|棕色衍生(Show)
Data Doginfo =狗字符串构建颜色

实例是难题的Doginfo在哪里
  greeting (Dog _    Skinny _    ) = "那只狗几乎没有任何东西。"
  greeting (Dog _    Fat    _    ) = "What a fat dog!"
  greeting (Dog name _      color) = "What a healthy " ++
                                     (地图char.tolower $ show颜色) ++
                                     " dog.  Hello, " ++ name ++ "!"


现在,重复上面提到的编译将给我们3d中奖规则正确的事物的可执行文件。
赞助
赞助
赞助
赞助
WTD.




邮政发布: 2004年12月31日星期五12:52  帖子主题:哈斯克尔介绍继续

更多关于可执行文件

既然我们有能力将Haskell程序编译为本机可执行文件,我们可能需要做一些事情。


  • 从我们自己内部执行另3d中奖规则程序。
  • 获取提供给我们计划的参数。


两者都是通过系统模块中的函数提供的。第3d中奖规则通过系统功能解决。最有用的示例可能是运行Windows“暂停”程序,该程序创建着名的“按任意键继续...”消息。

当程序完成工作时,这对于防止控制台窗口很有用。如果我通过双击生成的可执行文件编译并运行以下内容,T'LL打印邮件,但它会如此迅速,窗口将在我看到任何内容之前关闭。

代码:
模块主要在哪里

主要的:: IO ()
主要的 = Putstrln."Hello, world!"


相反,我想在程序结束时暂停,所以我编译:

代码:
模块主要在哪里

进口系统

主要的:: IO ExitCode
主要的= do putstrln"Hello, world!"
          system "pause"


有趣的是,系统函数返回3d中奖规则ExitCode,因此您可以判断您运行的程序是否成功。如果成功,则退回ExitSuccess。否则,退出ExitFailure。 ExitFailure构造函数也需要3d中奖规则int,因此您可以究竟介绍程序退出的代码。

我们可以测试暂停的成功。

代码:
模块主要在哪里

进口系统

主要的:: IO ExitCode
主要的= do putstrln"Hello, world!"
          result <- system "pause"
          case result of
            ExitSuccess   -> putStrLn "It worked."
            ExitFailure x -> putStrLn $ "Failure: " ++ show x
          system "pause"


现在,我提到将变量传递给程序。 getargs函数将以字符串列表的形式执行此操作。所以,让我们招呼传递给程序的名称。

代码:
模块主要在哪里

进口系统

主要的:: IO ExitCode
主要的= do名字<- getArgs
          let greetings =地图问候名称
              printAll   = mapM_ putStrLn
              greeting n = "Hello, " ++ name ++ "!"
          printAll greetings
          system "pause"


而现在是完全不同的东西

让我们为典型的副本程序建立快速替代,它将3d中奖规则文件占用并将其内容复制到另3d中奖规则文件中。

这应该涵盖:


  • 文件
  • 误差处理


要获得文件处理功能,我们需要IO模块。

让我们来看看打开文件并读取内容,然后将它们打印到屏幕上。

代码:
模块主要在哪里

导入IO.

主要的:: IO ()
主要=做fh<- openFile "bar.txt" ReadMode
          text <- hGetContents fh
          hClose fh
          putStrLn text


解剖......

代码:
打开文件"bar.txt" ReadMode


第3d中奖规则参数显然是要打开的文件的名称。第二个参数是打开文件的模式。我们还可以选择WriteMode,AppendMode或ReadWriiteMode。

代码:
hgetContents fh.


显然这会得到“bar.txt”的内容。

代码:
HCLOSE FH.


在这里我们正在关闭文件。

所以,现在我们可以打开文件,获取内容,然后关闭文件。下3d中奖规则目标是能够打开文件,写入它,然后关闭它。

代码:
模块主要在哪里

导入IO.

主要的:: IO ()
主要=做fh<- openFile "foo.txt" WriteMode
          hPutStr fh "Hello\nworld!"
          hFlush fh
          hClose fh


这里没有3d中奖规则新的。

简化文件的处理

但如果这是我们正在使用文件,我们可以用两个函数替换所有这些功能:readfile和writefile。

因此,让我们写3d中奖规则将3d中奖规则文件内容复制到另3d中奖规则文件中的程序。

代码:
模块主要在哪里

导入IO.

主要的:: IO ()
主要的=做文字<- readFile "foo.txt"
          writeFile "bar.txt" text


争论

当然,要更准确地模拟Copy命令,我们的程序应该在用户提供的文件名,而不是硬编码的文件中工作。

代码:
模块主要在哪里

导入IO.
进口系统

主要的:: IO ()
主要的=做args<- getArgs
          let i = args !! 0
              o = args !! 1
          text <- readFile i
          writeFile o text


误差处理

如果我们提供少于两个参数,这将由于“o = args !! 1”而失败。所以我们应该检查是否有至少两个参数。如果没有,请提醒用户。

代码:
模块主要在哪里

导入IO.
进口系统

主要的:: IO ()
主要的=做args<- getArgs
          if length args >= 2
           然后让我= args !! 0.
                     o = args !! 1
                 text <- readFile i
                 writeFile o text
           else hptstrln stderr.
                           "该程序至少需要两个参数。"


现在,如果我们尝试打开3d中奖规则不存在的读取文件,我们的程序将引发错误并终止。我们可以试图防止这种情况,但这非常令人疑惑,所以如果我们会让错误发生并“捕获”它,适当地使用,足够,捕获功能。

我们所需的行为是,如果要读取的文件不存在,则文本应该是空字符串。捕获功能允许我们通过提供错误发生的函数来执行此操作。

代码:
模块主要在哪里

导入IO.
进口系统

主要的:: IO ()
主要的=做args<- getArgs
          if length args >= 2
           然后让我= args !! 0.
                     o = args !! 1
                 text <- catch (readFile i)
                               (\_ -> return "")
                 writeFile o text
           else hptstrln stderr.
                           "该程序至少需要两个参数。"


这里唯一应该奇怪的是:

代码:
\ _ - > return ""


我们在这里看到的是另一种写作功能的方法。 backslash介绍函数的参数,以及 - >导致功能的实际肠道。在这种情况下的论点是错误本身,但我们并不关心其实际错误的原因,因此我们使用下划线。函数本身只是返回空字符串。

最后一件事

在最后3d中奖规则代码样本中,我们看到:

代码:
抓住(readFile i)
      (\_ -> return "")


您可能也看到的是使用:

代码:
readfile我`catch` \ _ - > return ""


这里,捕获的反击将两个参数翻转到操作员中。

您使用的这两种形式中的哪一种纯粹是一种风格问题,但要理解也很重要。
从上3d中奖规则显示帖子:   
   指数 -> 编程,一般编程 -> 功能规划
查看上3d中奖规则主题 告诉3d中奖规则朋友可打印的版本下载主题订阅本主题私人信息刷新页面 查看下3d中奖规则主题

11  [ 2 Posts ]
跳到:   


Style:  
搜索: