【问题标题】:Applying multiplication across lists in haskell list comprehension在haskell列表理解中跨列表应用乘法
【发布时间】:2015-02-09 10:40:14
【问题描述】:

haskell noob 在这里。我正在做Learn you a Haskell 并遇到了这个问题:

[ x*y | x <- [2,5,10], y <- [8,10,11]]

我改写如下

[ x*y | x <- [[1,2,3], [2,3,4]], y <- [[4,5,6],[5,6,7]] ]

编译器对我咆哮可能是因为我试图将一个列表与另一个列表相乘。但是,如果我想递归地将 xy 的每个子列表相乘,我该怎么做?

这是我得到的错误:

No instance for (Num [t0]) arising from a use of `*'
    Possible fix: add an instance declaration for (Num [t0])
    In the expression: x * y

更新

到目前为止,我已经到达这里:

[ [a*b | a <- x, b <- y] | x <- [[1,2,3],[2,3,4]], y <- [[4,5,6], [5,6,7]] ]

但这仍然返回一个列表列表。在 Haskell 中扁平化列表的优雅方式是什么?

【问题讨论】:

  • 你想要的输出是什么?
  • 我想将 x 中每个子列表的每个元素与 y 中每个子列表的每个元素相乘。然后展平成一个阵列。这有意义吗?
  • 提示:如果您使用第一个示例编写函数multList,则可以在第二个示例中替换x*y
  • 我如何使用multList?我是一个完整的 Haskell 菜鸟。
  • 他不希望你使用multList,他希望你创建一个....关键是,从数学上讲,有很多方法可以定义两个向量的乘法,因此 Haskell 没有为您提供默认值。但是,它确实为您提供了一种将其定义为您想要的任何东西的方法。

标签: haskell list-comprehension


【解决方案1】:

在 GHCI 中试试这个:

Prelude> let combinate xs ys = [ x*y | x<-xs, y<-ys ]
Prelude> concat [ combinate x y | x <- [[1,2,3], [2,3,4]], y <- [[4,5,6],[5,6,7]] ]
[4,5,6,8,10,12,12,15,18,5,6,7,10,12,14,15,18,21,8,10,12,12,15,18,16,20,24,10,12,14,15,18,21,20,24,28]

【讨论】:

    【解决方案2】:

    所以让我们尝试几种方法。我将使用 ghci 来说明一些例子:

    % ghci
    GHCi, version 7.8.2: http://www.haskell.org/ghc/  :? for help
    Loading package ghc-prim ... linking ... done.
    Loading package integer-gmp ... linking ... done.
    Loading package base ... linking ... done.
    λ [ x*y | x <- [2,5,10], y <- [8,10,11]]
    [16,20,22,40,50,55,80,100,110]
    λ -- so let's abstract that to a function
    λ let multList xs ys = [ x*y | x <- xs, y <- ys ]
    λ multList [2,5,10] [8,10,11]
    [16,20,22,40,50,55,80,100,110]
    λ -- let's try a simpler example
    λ multList [1] [1]
    [1]
    λ -- now let's see if we can get your code working
    λ -- (I tweaked the variable names, but that's just cosmetic)
    λ [ xs*ys | xs <- [[1,2,3], [2,3,4]], ys <- [[4,5,6],[5,6,7]] ]
    
    <interactive>:13:1:
        No instance for (Num [t0]) arising from a use of ‘it’
        In a stmt of an interactive GHCi command: print it
    λ -- yup, that's the error alright
    λ -- let's skip multiplying. what else can we do with xs and ys?
    λ -- well, we could create the pair (xs,ys)
    λ [ (xs,ys) | xs <- [[1,2,3], [2,3,4]], ys <- [[4,5,6],[5,6,7]] ]
    [([1,2,3],[4,5,6]),([1,2,3],[5,6,7]),([2,3,4],[4,5,6]),([2,3,4],[5,6,7])]
    λ -- that's each pair of sublists, but we want to compute the products of each element
    λ -- fortunately, that's exactly what multList does!
    λ :t multList
    multList :: Num t => [t] -> [t] -> [t]
    λ [ multList xs ys | xs <- [[1,2,3], [2,3,4]], ys <- [[4,5,6],[5,6,7]] ]
    [[4,5,6,8,10,12,12,15,18],[5,6,7,10,12,14,15,18,21],[8,10,12,12,15,18,16,20,24],[10,12,14,15,18,21,20,24,28]]
    λ -- so that creates four sublists, one for each pair of lists.
    λ -- what if we want to flatten that out?
    λ -- well, we could just use `concat`
    λ :t concat
    concat :: [[a]] -> [a]
    λ concat [ multList xs ys | xs <- [[1,2,3], [2,3,4]], ys <- [[4,5,6],[5,6,7]] ]
    [4,5,6,8,10,12,12,15,18,5,6,7,10,12,14,15,18,21,8,10,12,12,15,18,16,20,24,10,12,14,15,18,21,20,24,28]
    λ -- alternately, we could try to inline our definition of `multList` and see where that gets us
    λ [ [ x*y | x <- xs, y <- ys ] | xs <- [[1,2,3], [2,3,4]], ys <- [[4,5,6],[5,6,7]] ]
    [[4,5,6,8,10,12,12,15,18],[5,6,7,10,12,14,15,18,21],[8,10,12,12,15,18,16,20,24],[10,12,14,15,18,21,20,24,28]]
    λ -- nothing yet, but see how we've got two list comprehensions?
    λ -- let's combine them into one!
    λ [ x*y | xs <- [[1,2,3], [2,3,4]], ys <- [[4,5,6],[5,6,7]], x <- xs, y <- ys ]
    [4,5,6,8,10,12,12,15,18,5,6,7,10,12,14,15,18,21,8,10,12,12,15,18,16,20,24,10,12,14,15,18,21,20,24,28]
    λ -- hey, that worked!
    

    【讨论】:

    • 这太棒了,非常有帮助。谢谢。
    猜你喜欢
    • 2016-01-22
    • 2022-01-08
    • 1970-01-01
    • 2018-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多