- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想这里的每个人都已经看到过这些(或至少类似)问题之一,但我仍然需要问,因为我在任何地方都找不到这个问题的答案(主要是因为我不知道我到底是什么)应该寻找)
我写了这个小脚本,其中 printTriangle 应该打印出帕斯卡三角形。
fac = product . enumFromTo 2
binomial n k = (product (drop (k-1) [2..n])) `div` (fac (n-k))
pascalTriangle maxRow =
do row<-[0..maxRow-1]
return (binomialRow row)
where
binomialRow row =
do k<-[0..row]
return (binomial row k)
printTriangle :: Int -> IO ()
printTriangle rows = do row<-(triangle)
putStrLn (show row)
where
triangle = pascalTriangle rows
现在,出于对训练有素的人来说可能显而易见的原因,但对我来说完全笼罩在神秘之中,当我尝试在 ghci 中加载它时,出现以下错误:
Couldn't match expected type `IO t0' with actual type `[[Int]]'
In a stmt of a 'do' expression: row <- (triangle)
In the expression:
do { row <- (triangle);
putStrLn (show row) }
In
an equation for `printTriangle':
printTriangle rows
= do { row <- (triangle);
putStrLn (show row) }
where
triangle = pascalTriangle rows
我想做的是像这样调用 printTriangle :
printTriangle 3
我得到这个输出:
[1]
[1,1]
[1,2,1]
如果有人可以向我解释为什么我在这里所做的事情不起作用(说实话,我不太确定我在这里到底做了什么;我习惯了命令式语言,而整个函数式编程的事情就是对我来说仍然很困惑),以及如何以一种不那么愚蠢的方式做到这一点,那就太好了。
提前致谢。
最佳答案
您在评论中说您认为列表是 monad,但现在您不确定 - 好吧,您是对的,列表是 monad!那么为什么你的代码不起作用呢?
嗯,因为IO
也是一个单子(monad)。所以当编译器看到printTriangle :: Int -> IO ()
时,然后是 do 符号,它表示“啊哈!我知道该怎么做!他正在使用 IO monad!”尝试想象一下,当它发现里面不是 IO monad,而是列表 monad 时,它会感到多么震惊和沮丧!
所以这就是问题所在:要打印,并与外界打交道,你需要使用 IO monad;在函数内部,您尝试使用列表作为 monad。
让我们看看这是一个什么问题。 do-notation 是 Haskell 的语法糖,用来引诱我们进入它的蛋糕屋并吃掉我们......我的意思是它是 >>=
的语法糖。 (发音为“bind”)来引诱我们使用 monad(并享受它)。所以我们写 printTriangle
使用绑定(bind):
printTriangle rows = (pascalTriangle rows) >>= (\row ->
putStrLn $ show row)
好吧,这很简单。现在我们看到什么问题了吗?好吧,让我们看看类型。绑定(bind)的类型是什么?胡格尔 说:(>>=) :: Monad m => m a -> (a -> m b) -> m b
。好的,谢谢胡格尔。所以基本上,bind 想要一个 monad 类型包装一个类型 a 个性,一个将 a 类型个性转换为(相同)monad 类型包装一个 type-b 个性的函数,并最终得到(相同)monad 类型包装一个类型 - b 个性。
所以在我们的printTriangle
中,我们有什么?
pascalTriangle rows :: [[Int]]
-- 所以我们的单子(monad)是 []
,个性为[Int]
(\row -> putStrLn $ show row) :: [Int] -> IO ()
-- 这里的 monad 是 IO,个性是 ()
好吧,废话。 Hoogle 非常清楚地告诉我们,我们必须匹配我们的 monad 类型,相反,我们给出了 >>=
一个列表 monad,以及一个生成 IO monad 的函数。这使得 haskell 表现得像个 child 子:它闭上眼睛,跺在地板上尖叫着“不!不!不!”甚至不会查看你的程序,更不用说编译它了。
那么我们如何安抚 Haskell 呢?嗯,其他人已经提到了mapM_
。向顶级函数添加显式类型签名也是一个好主意——它有时可以帮助您更快而不是更晚地获得编译错误(并且您会得到它们;毕竟这是 Haskell :) ),这使得更容易理解错误消息。
我建议编写一个函数来将你的 [[Int]]
成一个字符串,然后将字符串单独打印出来。通过将字符串转换与 IO 麻烦分开,这将使您能够继续学习 Haskell,而不必担心 mapM_
和 friend 们,直到你做好准备。
showTriangle :: [[Int]] -> String
showTriangle triangle = concatMap (\line -> show line ++ "\n") triangle
或
showTriangle = concatMap (\line -> show line ++ "\n")
然后printTriangle
容易得多:
printTriangle :: Int -> IO ()
printTriangle rows = putStrLn (showTriangle $ pascalTriangle rows)
或
printTriangle = putStrLn . showTriangle . pascalTriangle
关于Haskell初学者,尝试输出一个列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8100514/
说真的,你怎么能在不发疯的情况下处理所有这些异常呢?我是不是读了太多关于异常处理的文章或什么?我尝试重构了几次,但每次似乎都以更糟糕的结果告终。也许我应该承认确实会发生异常(exception)情况,
背景 两者 try/rescue和 try/catch是 Elixir 中的错误处理技术。根据 corresponding chapter在介绍指南中。 Errors can be rescued u
每当我尝试在 Raspberry PI 上运行此 python 脚本时,我都会遇到问题: import socket import sys # Create a TCP/IP socket sock
我想知道一些关于 PHP 的 try , catch声明。 让我们考虑以下示例。 abstract class ExceptionA extends Exception {} class Except
我的 laravel v5.4 项目中有两个模型,user 和 admin。 在 config/auth.php 中,我向守卫和提供者添加了管理员,如下所示: 'guards' => [ 'w
try: r = requests.get(url, params={'s': thing}) except requests.ConnectionError, e: print e
我有以下代码。 但是,它并不能捕获所有错误,而我仍然会收到“throw er;//未处理的'错误'事件”。 为什么是这样? app.post('/api/properties/zip/:zip/bed
问题与细节 我正在使用自定义错误处理,遇到的错误之一是“路径中的非法字符”。我有一个自定义函数,旨在通过路径字符串查找此类非法字符,并在找到它们时引发自定义错误。但是我发现,取决于非法字符,Test-
This question already has answers here: How do I catch a numpy warning like it's an exception (not j
我正在使用其他人的代码,但我不熟悉try/catch,因此我举了一个类似的小例子。在第11行上,如果我写了error(''),似乎没有发现错误并增加了索引j。但是,编写error(' ')或error
我在我的一个程序中遇到了这个问题,在这种情况下,尝试/异常(exception)的错误使程序变得更好,以防用户意外输入了他们不应该输入的内容。它仍然给我错误,我为为什么感到困惑。如果对我的问题确实很重
我在尝试TRY ... CATCH块时遇到问题。有人可以解释为什么以下代码无法执行我的sp吗? DECLARE @Result int SET @Result = 0 BEGIN TRY SE
我有一个相当大的 powershell 脚本,其中包含许多(20 多个)执行各种操作的函数。 现在所有代码实际上都没有任何错误处理或重试功能。如果某个特定的任务/功能失败,它就会失败并继续。 我想改进
为什么我尝试时需要导入 inputmismatchException catch(InputMismatchException e){ System.out.println("
我对此感到困惑 - 我为辅助方法编写了一个 try/catch 。它的目的是捕获任何无效输入(任何不是“男性”或“女性”的内容(没有特定情况)。如果输入无效,它将通知用户,然后让他们重试。如果有效,则
我有时会发现自己处于如下场景。尽可能简单地陈述问题 “有时我会创建一段代码,Java 让我将其包含在 try/catch 语句中。我没有使用 catch,所以我将其留空。为什么这是错误的?” boo
我有点困惑为什么当我不使用 Try block 时会出现 Try block 错误。 我在代码块底部附近收到错误通知。如果我不使用 try/catch,有人可以向我解释为什么会发生这种情况吗? 它是否
我已经盯着我的电脑两个小时了,我不知道我做错了什么。谁能帮助我看到光明? package blackjack; import java.util.Random; import java.util.Sc
我想将方法保存在 Enum 中,但 Class.getDeclaredMethod 抛出 NoSuchMethodException,那么我该如何处理呢?我的代码: public enum Car
这个问题已经有答案了: Executing multi-line statements in the one-line command-line (18 个回答) 已关闭 3 年前。 如何使用try.
我是一名优秀的程序员,十分优秀!