Haskell中可能无限的元组列表

时间:2017-11-29 17:27:35

标签: list haskell tuples factors

我有一个问题我无论如何都无法解决。这是关于除数的后续任务。

第一个是定义一个函数,它将数字 k 的所有正除数放入一个列表中

编辑:意外地写了错误的代码(当你有一个函数除数和除数时,这就是你得到的......只是看着列表如何反应。) 关于在列表中使用倍数的问题,这不应该在这里发生,但它的速度会慢一些。

divisor :: Int -> [Int]
divisor k = divisor' 1 k
 where
  divisor' n k  | n > k = []
              | k `mod` n == 0 = (n:result)
              | otherwise = result
   where result = divisor' (n+1) k

到目前为止一切顺利。

我的以下任务是编写一个函数,该函数返回元组列表(x,xs),其中x是自然数/= 0xs是所有正数的列表x的除数。

看起来应该是这样的:

take 7 trueDivisors 
[(1,[]),(2,[1]),(3,[1]),(4,[1,2]),(5,[1]),(6,[1,2,3]),(7,[1])]

take代表究竟是什么?现在我重新阅读任务可能是我的问题。通常函数只能通过他们的名字调用...试图让trueDivisors k工作)

我已经尝试了很多,比如使用我的第一个函数来获取元组内部列表中的除数,这些除数没有用完。语法错误语法错误。

也许有人可以帮我一点,或者给我一个提示。可悲的是,脚本中没有类似的东西。谷歌也不太热衷。

提前致谢!

3 个答案:

答案 0 :(得分:2)

这是一个提示。如果你map divisors [1..7],你会得到:

[[1,1],[1,2],[1,3],[1,2,2,4],[1,5],[1,2,3,6],[1,7]]

这些是您要创建的关联列表的第二个组件,除非您有一个小错误,除非允许多次返回相同的除数。 (提示:您可以使用divisors编写一个很好的单行版filter,但快速解决方法是Data.List.nub。)您想要返回:

[(1,[1]),(2,[1,2]),(3,[1,3]),(4,[1,2,4]),...]`

解决此问题的一种简单方法是编写辅助函数makeAssoc :: Int -> (Int, [Int]),然后编写map makeAssoc [1..]。此功能可以调用divisors

另一个是采用两个列表[1..](map divisors [1..])。第一个类型为[Int],第二个类型为[[Int]],您希望结果类型为[( Int, [Int] )]。因此,在Prelude中查找将两个类型[a][b]列表压缩到一对[(a,b)]列表中的函数。也就是说,查找类型为签名[a] -> [b] -> [(a,b)]的函数,并查看它们中是否有任何符号。

如果弄清楚这些类型似乎很复杂,请不要担心:你可以让GHC为你做这件事!如果你写,

divisorAssocs :: [( Int, [Int] )]
divisorAssocs = map _ is
  where is :: [Int]
        is = [1..]

GHC会将_识别为打字洞,并告诉您需要填写的内容:

• Found hole: _ :: Int -> (Int, [Int])

同样,如果你用另一种方式写一个洞:

divisorAssocs :: [( Int, [Int] )]
divisorAssocs = _ is (map divisors is)
  where is :: [Int]
        is = [1..]

给你:

• Found hole: _ :: [Int] -> [[Int]] -> [(Int, [Int])]

答案 1 :(得分:0)

在Haskell中,有限列表和无限列表之间并没有真正的区别。问题是要求你创建一个名为trueDivisors的变量(尽管Haskell变量不变),其类型为[(Int, [Int])]

让我们先来看看如何制作一些无限列表

myFirstInfiniteList :: [Int]
myFirstInfiniteList = [1..]
powers :: [Int]
powers = powers’ 1 where
  powers’ n = n : n * 2
myThirdInfiniteList :: [(Int,[Int])]
myThirdInfiniteList = map it [1..] where
  it n = (n, [1..n])

现在Haskell事先并不知道列表是否是无限的,所以如果你试图打印一个列表,它将永远存在。所以你可以使用take函数返回列表的前n个元素(其中n是第一个参数)

我认为这应该足以让你自己解决它。

trueDivisors :: [(Int,[Int])]
trueDivisors = {- you need to do this -}

答案 2 :(得分:0)

你如何配对数字和除数?

一个简单的实现是:

pair n = (n, divisors n)

剩下的是将对映射到无限自然数序列并获取所需数量的元素

take 7 $ map pair [1..]