试图通过Haskell查找GCD。我的代码中的错误在哪里?

erd*_*asa 4 haskell greatest-common-divisor

作为练习,我尝试自己编写此代码,但是我被卡住了,不知道代码中的错误在哪里。

module Hf where

--sumSquaresTo :: Integer -> Integer
--sumSquaresTo x = sum [ n^2 | n <- [1..x] ]

divides a b = b `mod` a == 0

divisors a = [n | n <- [1..a], n `divides` a ]


lnko :: Integer -> Integer -> Integer
lnko a b = [n | n <- [1..max(a b)], (n `divides` a) && (n `divides` b) ]
Run Code Online (Sandbox Code Playgroud)

GHCI输出:

error:
    * Couldn't match expected type `Integer'
                  with actual type `[a0 -> a0]'
    * In the expression:
        [n | n <- [1 .. max (a b)], (n `divides` a) && (n `divides` b)]
      In an equation for `lnko':
          lnko a b
            = [n | n <- [1 .. max (a b)], (n `divides` a) && (n `divides` b)]
   |
12 | lnko a b = [n | n <- [1..max(a b)], (n `divides` a) && (n `divides` b) ]
   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error:
    * Couldn't match expected type `Integer -> a0'
                  with actual type `Integer'
    * The function `a' is applied to one argument,
      but its type `Integer' has none
      In the first argument of `max', namely `(a b)'
      In the expression: max (a b)
   |
12 | lnko a b = [n | n <- [1..max(a b)], (n `divides` a) && (n `divides` b) ]
   |                              ^^^

error:
    * Couldn't match expected type `a0 -> a0'
                  with actual type `Integer'
    * In the second argument of `divides', namely `a'
      In the first argument of `(&&)', namely `(n `divides` a)'
      In the expression: (n `divides` a) && (n `divides` b)
    * Relevant bindings include
        n :: a0 -> a0
          (bound at C:\\Users\erdos\Desktop\haskell\hazi1.hs:12:17)
   |
12 | lnko a b = [n | n <- [1..max(a b)], (n `divides` a) && (n `divides` b) ]
   |                                                  ^

error:
    * Couldn't match expected type `a0 -> a0'
                  with actual type `Integer'
    * In the second argument of `divides', namely `b'
      In the second argument of `(&&)', namely `(n `divides` b)'
      In the expression: (n `divides` a) && (n `divides` b)
    * Relevant bindings include
        n :: a0 -> a0
          (bound at C:\\Users\erdos\Desktop\haskell\hazi1.hs:12:17)
   |
12 | lnko a b = [n | n <- [1..max(a b)], (n `divides` a) && (n `divides` b) ]
   |                                                                     ^
Failed, no modules loaded.
Run Code Online (Sandbox Code Playgroud)

Ign*_*rov 7

好吧,这里有两个错误。

  1. 在Haskell中,您无需编写max(a b),而只需编写max a b。这称为currying

  2. 您的职能实际上找到了所有共同因素。例如:

    ? lnko 8 16
    [1,2,4,8]
    
    Run Code Online (Sandbox Code Playgroud)

    如果您相应地修改类型签名,它将起作用。或者您可以选择某种因素之一。

总的来说,这是很棒的代码。继续!


Wil*_*sem 5

类型不匹配。确实,在您的职能中:

lnko :: Integer -> Integer -> Integer
lnko a b = [n | n <- [1..max(a b)], (n `divides` a) && (n `divides` b) ]
Run Code Online (Sandbox Code Playgroud)

您在这里返回列表,因为您使用列表理解。此外,您犯了一些语法错误。例如,这max (a b)意味着您将函数应用程序a用作函数和b参数。这应该是max a b

您可以将其重写为:

lnko :: Integer -> Integer -> Integer
lnko a b = maximum [n | n <- [1..min a b], n `divides` a, n `divides` b ]
Run Code Online (Sandbox Code Playgroud)

但是,尽管如此,您还是在这里使用一种方法,对所有可能的分隔符进行迭代,以找到最大的分隔符。例如,您可以使用欧几里得算法 [wiki],该算法通常会胜过线性搜索:

lnko :: Integral i => i -> i -> i
lnko a 0 = a
lnko a b = lnko b (mod a b)
Run Code Online (Sandbox Code Playgroud)

这也将更加安全,例如,如果在参数中使用负数。