Lan*_*ara 1 recursion haskell type-inference
我正在努力学习Haskell,这是我在函数式编程中的第一种方法.我在创建一个以数字作为输入并逐个打印该数字的函数时遇到了一些麻烦,直到0.
printDescending n = if n > 0
then printDescending n - 1 return n
else return n - 1
Run Code Online (Sandbox Code Playgroud)
我希望能够做到printDescending 20并输出20,19,18 ...... 2,1,0.但是我收到了这个错误:
> • Non type-variable argument
> in the constraint: Num ((a -> m a) -> a1 -> m1 a1)
> (Use FlexibleContexts to permit this)
> • When checking the inferred type
> printDescending :: forall (m :: * -> *) a (m1 :: * -> *) a1.
> (Ord a1, Num ((a -> m a) -> a1 -> m1 a1), Num (m1 a1), Num a1,
> Monad m1, Monad m) =>
> a1 -> m1 a1 Failed, modules loaded: none.
Run Code Online (Sandbox Code Playgroud)
我想这可能是我的语法.有人有见识吗?
你已经表明:
printDescending n = if n > 0
then printDescending n - 1 return n
else return n - 1
Run Code Online (Sandbox Code Playgroud)
让我们首先看一下如何解析它:
printDescending n = if n > 0
then (printDescending n) - (1 return n)
else (return n) - 1
Run Code Online (Sandbox Code Playgroud)
可能不是你想要的,对吧?请注意中缀运算符,例如-绑定比函数应用程序更紧密.另外看看'return'并不特别 - 它也只是函数应用程序.最后,你实际上没有包含对任何类型print命令的调用,所以无论你使用什么语言,我都不希望它能够运行.
解决这些问题,让我们首先提供一个类型签名(有点像C中的函数原型):
printDescending :: Int -> IO ()
Run Code Online (Sandbox Code Playgroud)
所以printDecending接受一个参数,一个Int,并做一些IO.在()被称为"单位",谁知道下的程序员的第一课,你应该能够在精神上认为,由于void并确定.
现在身体怎么样?那么你的if陈述很好:
printDescending n =
if n > 0
then ...
else...
Run Code Online (Sandbox Code Playgroud)
该else声明是一个有点怪异.即使修复解析,你为什么要0-1?让我们回到单位:
printDescending n =
if n > 0
then ...
else return ()
Run Code Online (Sandbox Code Playgroud)
现在对于then分支机构,你真的想要两件事.1.打印值2.递归调用下一个最小值的printDecending.有一点符号,do我们将用它来排序两个IO操作,但除此之外,这两个任务直接转换为命令:
printDescending n =
if n > 0
then do print n
printDescending (n - 1)
else return ()
Run Code Online (Sandbox Code Playgroud)
现在让我们再做一步.由于这不是C/Java/etc并且是一种函数式语言,因此人们会期望一种声明式的风格.为此,让我们使用guards而不是if语句来声明printDescending:
printDescending n
| n > 0 = do print n
printDescending (n-1)
| otherwise = return ()
Run Code Online (Sandbox Code Playgroud)
备择方案
现在我将提供一些替代方案,仅用于举例说明.
如果您不关心负值,那么我们可以通过以下方式终止于零:
printDescending 0 = return ()
printDescending n =
do print n
printDescending (n-1)
Run Code Online (Sandbox Code Playgroud)
或者我们可以使用列表推导来构建值列表,然后print对列表的每个元素执行.我们可以这样做forM_(参见更惯用的mapM_),它对列表的每个元素执行一个操作并抛弃结果,返回单位.
printDescending n = forM_ [n,n-1..1] print
Run Code Online (Sandbox Code Playgroud)
最后,如果您想进行更快速的交流,请考虑加入irc.freenode.net上的#haskell频道.那里有一个伟大的团队,这就是我所知道的许多Haskell程序员的开始.
| 归档时间: |
|
| 查看次数: |
1006 次 |
| 最近记录: |