Haskell通过递归向列表中添加元素
我试图理解Haskell中的列表,但我遇到了一些不确定的事情。是否可以通过循环进行迭代,并在每次迭代时向列表中添加一项?为了回答这个问题,我编写了以下代码:Haskell通过递归向列表中添加元素,haskell,ghci,Haskell,Ghci,我试图理解Haskell中的列表,但我遇到了一些不确定的事情。是否可以通过循环进行迭代,并在每次迭代时向列表中添加一项?为了回答这个问题,我编写了以下代码: list = [] addNumbers 0 = return () addNumbers n = do print n n : list addNumbers (n-1) 我原以为这会起作用,但它似乎给出了错误“无法将类型“[]”与“IO”匹配”。我不太清楚为什么会出现这个错误,因为没有要求用户输入或输出。我认
list = []
addNumbers 0 = return ()
addNumbers n =
do
print n
n : list
addNumbers (n-1)
我原以为这会起作用,但它似乎给出了错误“无法将类型“[]”与“IO”匹配”。我不太清楚为什么会出现这个错误,因为没有要求用户输入或输出。我认为这可能与“print n”有关,但如果没有这一行,它似乎不起作用
提前为任何帮助喝彩这不会像您认为的那样,在Haskell中,一切都是不可变的(一旦给它一个值,该值就不能更改)。您可能想做的是:
addNumbers :: Int -> IO [Int]
addNumbers 0 = return []
addNumbers n = do print n
ns <- addNumbers (n-1)
return (n:ns)
注意addNumbers
的签名,它接受Int
并返回由IO monad封装的Int
列表。它必须由IO monad封装,因为对打印的调用在IO monad中返回()
,否则将无法打印该值
如果您只想在列表前面添加一个Int
,那么您可以很容易地做到这一点
foo 0 = [0]
foo n = n:foo (n-1)
这不会像您认为的那样,在Haskell中,一切都是不可变的(一旦给它一个值,该值就不能更改)。您可能想做的是:
addNumbers :: Int -> IO [Int]
addNumbers 0 = return []
addNumbers n = do print n
ns <- addNumbers (n-1)
return (n:ns)
注意addNumbers
的签名,它接受Int
并返回由IO monad封装的Int
列表。它必须由IO monad封装,因为对打印的调用在IO monad中返回()
,否则将无法打印该值
如果您只想在列表前面添加一个Int
,那么您可以很容易地做到这一点
foo 0 = [0]
foo n = n:foo (n-1)
通常在Haskell中,您会将数字的打印(不纯操作)与创建此类列表(纯操作)分开。如果您只是在调试print语句,那么可以使用类似Debug.Trace的东西来欺骗typechecker(同样,仅用于调试目的)。您正在将来自
print
的IO
单子和列表单子混合在同一个绑定中!请记住,a>=\a->
,因此它需要有非常特殊的类型。通常在Haskell中,您会将数字的打印(不纯操作)与创建这样的列表(纯操作)分开。如果您只是在调试print语句,那么可以使用类似Debug.Trace的东西来欺骗typechecker(同样,仅用于调试目的)。您正在将来自print
的IO
单子和列表单子混合在同一个绑定中!请记住a>=\a->
,因此它需要有非常特殊的类型。我一直在玩这个,它工作得非常好。只是另一个小问题,我试图添加一个if语句。因此,如果这个数字可以被3整除,那么它就会被添加到列表中,如果不是的话,它只会拿走一个。它似乎不喜欢ns@Jordan将返回(n:ns)
替换为如果n`mod`3==0,则返回(n:ns)否则返回(tail ns)
。为此,您不需要在if
下运行addNumbers
。(注意,因为这可能会试图从空列表中删除一个元素)谢谢chi,有什么原因我不能在输出中调用“length”吗?我想这是一个列表。但是,如果我删除随机用户名代码中的打印并调用“length(addNumbers 3)”,则会出现错误。你知道吗?@Jordan你有一个类型不匹配:length
有类型[a]->Int
,但是你的列表有类型IO[Int]
。试试fmap length$addNumbers 3
。我一直在玩这个,它工作得很好。只是另一个小问题,我试图添加一个if语句。因此,如果这个数字可以被3整除,那么它就会被添加到列表中,如果不是的话,它只会拿走一个。它似乎不喜欢ns@Jordan将返回(n:ns)
替换为如果n`mod`3==0,则返回(n:ns)否则返回(tail ns)
。为此,您不需要在if
下运行addNumbers
。(注意,因为这可能会试图从空列表中删除一个元素)谢谢chi,有什么原因我不能在输出中调用“length”吗?我想这是一个列表。但是,如果我删除随机用户名代码中的打印并调用“length(addNumbers 3)”,则会出现错误。你知道吗?@Jordan你有一个类型不匹配:length
有类型[a]->Int
,但是你的列表有类型IO[Int]
。请尝试fmap length$addNumbers 3
。