Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell中使用列表的不同fibonacci实现_Haskell_Functional Programming_State_Fibonacci_Imperative Programming - Fatal编程技术网

Haskell中使用列表的不同fibonacci实现

Haskell中使用列表的不同fibonacci实现,haskell,functional-programming,state,fibonacci,imperative-programming,Haskell,Functional Programming,State,Fibonacci,Imperative Programming,我在博客上搜索了一个类似于我想要的斐波那契实现。虽然关于Haskell的斐波那契实现有很多问题,但什么都没有出现 我想要一个递归斐波那契函数(速度不重要),它在每次调用斐波那契函数时将每个斐波那契数附加到一个全局列表。我是哈斯克尔的新手,有着非常重要的背景。这是我认为有效的方法,但没有达到目的 fibos = [] fib 0 = 1 fib 1 = 1 fib n = (fib(n-1) + fib(n-2)):fibos main = do putStrLn "Please

我在博客上搜索了一个类似于我想要的斐波那契实现。虽然关于Haskell的斐波那契实现有很多问题,但什么都没有出现

我想要一个递归斐波那契函数(速度不重要),它在每次调用斐波那契函数时将每个斐波那契数附加到一个全局列表。我是哈斯克尔的新手,有着非常重要的背景。这是我认为有效的方法,但没有达到目的

fibos = []

fib 0 = 1
fib 1 = 1
fib n = (fib(n-1) + fib(n-2)):fibos


main = do 
    putStrLn "Please enter a number:"
    n <- readLn
    fib n
    print fibos
fibos=[]
fib 0=1
fib 1=1
fib n=(fib(n-1)+fib(n-2)):fibos
main=do
putStrLn“请输入一个数字:”

n在纯函数式编程中,不能使用全局可变变量。因此,如果您定义一个全局值
fibos=[]
,那么该列表将永远是一个空列表。相反,如果您想要一个不可变的顶级定义,那么将其固定为n个Fibonacci数,其中n是在运行时确定的,
fibs
没有参数,这将变得很困难

另一种方法是Haskell的lazy求值,它使您能够为所有Fibonacci数创建一个顶级定义,但它们将仅在请求的范围内进行计算

fibs :: [Integer]
fibs = 1:1:zipWith (+) fibs (tail fibs)
或者不那么花哨:

fibs :: [Integer]
fibs = fib 0 1
  where fib a b = b : fib b (a+b)
然后,您可以根据需要提取任意多个斐波那契数:

main :: IO ()
main = do
  putStr "n: "
  n <- readLn
  putStrLn $ "Fibs: " ++ show (take n fibs)
main::IO()
main=do
putStr“n:”
n编辑:

如果您只需要查看导致fib n
的值序列,则应使用以下内容:

fibs=0:1:zipWith(+)fibs(尾部fibs)
fib n=(取n个fib,fib!!n)
其工作原理如下:

*Main>fib 0
([],0)
*Main>fib1
([0],1)
*Main>fib 10
([0,1,1,2,3,5,8,13,21,34],55)
如果需要,可以使用State monad来分隔计算的列表方面,但它只表示在有限范围内的“全局”列表(例如
main
函数)。这是你在哈斯克尔土地上最接近你想要的东西

正确的方法

我想你是为了实现梦想而做的?如果是,则基本上在
fib
的任何基于列表的实现的引擎盖下已经有一个全局列表-任何
fib
的调用方都使用Haskell(例如GHC)运行时在引擎盖下使用的相同的延迟评估列表;该列表中已计算的任何元素都不会重新计算

fibs=0:1:zipWith(+)fibs(尾部fibs)
-这里,
fibs
是一个全局列表,虽然您不能显式/手动地对其进行变异,但通过访问其中的单个元素(
fibs!!n
),您间接地导致了基础列表在运行时向其添加新值时发生变异


错误的方法(如果您不打算在实际代码中使用此方法,请继续)

另一方面,如果您只是为了拥有该列表而需要该列表,例如为了调试或其他一些奇怪的原因,您可以使用非常丑陋且不安全的黑客,例如以下基于
IORef
的解决方案,但请记住坚持使用以
不安全
结尾的函数名,本着stdlib如何标记所有不安全呼叫的精神,使使用这些呼叫的人意识到危险

import Data.IORef
导入System.IO.Unsafe(unsafePerformIO)
FibsStorage不安全::IORef[整数]
FibsStorage不安全=未安全性能$newIORef[]
--这是一个使用纯定义的
--来计算值,然后存储它
--在全局可变IORef中
fibN=unsafePerformIO(updateFibs-ret)`seq`ret
哪里
ret=fib'n
updateFibs x=do

old如果可以取回列表,您可以做类似的事情:

fibs 0 = [0]
fibs 1 = [0,1]
fibs n = let fs@(f1:f2:_) = fibs (n-1) 
         in (f1+f2) : fs
然后
fibs 10
将返回
[55,34,21,13,8,5,3,2,1,1,0]
。请注意,按照相反的顺序构建列表可能是浪费或更复杂的,因为Haskell列表只在“前端”运行。对于奇怪的
fs@(f1:f2:)
,请咨询(
@
是“as”模式)

对于“实”斐波那契函数,只需返回头部:

fib n = head (fibs n)
我认为这个版本与您的意图非常接近,而且它的性能也不错。然而,这段代码不是很地道。这里的典型方法是无限列表(如其他一些答案所示)


请允许我个人说一句话:我发现在学习哈斯克尔时,“命令式”知识更令人恼火,而不是更有帮助。我认为您应该有意识地尝试“忘记”或“忘却”您所知道的(命令式)编程,以便“摸索”函数式编程。

您不能变异
fibos
,它总是空列表。该解析错误可能是由于缩进造成的。将
putStrLn
移动到下一行-一个
do
中的所有语句都必须具有相同的缩进。这个“全局列表”到底有什么用?你为什么需要它,你想用它做什么?它应该按什么顺序包含数字?我认为你没有正确地解释你的作业。您能一字不差地分享吗?@Bergi稍后将使用该列表计算列表中所有元素的总和和乘积。我的作业说明中说:“当序列中的每个数字生成时,该数字会被添加到包含生成的数字的列表中”。它也必须是一个递归函数。我对斐波那契函数的实现仅用于教育目的,其次,当用户输入8时,它必须打印[0,1,1,2,3,5,8],而不是[0,1,1,2,3,5,8,13]如果用户输入9,它也应该打印[0,1,1,2,3,5,8,8],因为没有fib数字9,也没有[0,1,1,2,3,5,8,13,21]有9个元素。如何实现这样的功能呢?看,伙计,这不是一个“做我的作业”态度的网站-我已经向你展示了如何
import Data.List

fibo :: Int -> Int
fibo 0 = 0
fibo 1 = 1
fibo n = fibo (n-1)+fibo(n-2)


fiboList x =map fibo [1..x]

main = do
    print ( fiboList 35 )
import Data.List

fibo :: Int -> Int
fibo 0 = 0
fibo 1 = 1
fibo n = fibo (n-1)+fibo(n-2)


fiboList x =map fibo [1..x]

main = do
    print ( fiboList 35 )