首页 文章

期望类型与类型定义不同

提问于
浏览
0

我现在正试图解决Project Euler的第9个问题,但是Haskell不会停止向我大吼大叫关于不匹配的类型 . 问题是,ghci告诉我它期望的类型与函数类型定义中给出的类型不同 .

这是代码:

solvePyth :: Int -> Int -> Float
solvePyth x y
    |valid = x * y * z
    |otherwise = if y < x then solvePyth x (y + 1) else solvePyth (x + 1) 1
    where z = sqrt $ fromIntegral $ x^2 + y^2
          valid = (x^2 + y^2 == z^2) && (x + y + z == 1000)

这是我得到的错误:

Prelude> :l debug
[1 of 1] Compiling Main             ( debug.hs, interpreted )

debug.hs:3:14:
    Couldn't match expected type `Float' with actual type `Int'
    In the first argument of `(*)', namely `x'
    In the first argument of `(*)', namely `x * y'

debug.hs:3:18:
    Couldn't match expected type `Float' with actual type `Int'
    In the second argument of `(*)', namely `y'
    In the first argument of `(*)', namely `x * y'

debug.hs:6:33:
    Couldn't match expected type `Int' with actual type `Float'
    In the first argument of `(^)', namely `z'
    In the second argument of `(==)', namely `z ^ 2'
Failed, modules loaded: none.

我不明白为什么 (*)(^) 期待Floats和Ints,当检查他们用 :t 输入ghci时,他们的争论只需要被认为是Nums .

1 回答

  • 0

    以下是修复输入问题的一种方法:

    solvePyth :: Int -> Int -> Float
    solvePyth x' y'
      | valid = x * y * z
      | otherwise = if y' < x' then solvePyth x' (y' + 1) else solvePyth (x' + 1) 1
      where z = sqrt (x^2 + y^2)
            (x, y) = (fromIntegral x', fromIntegral y')
            valid = (x^2 + y^2 == z^2) && (x + y + z == 1000)
    

    (*)(^) 将适用于一般安装在 Num 类中的参数,但重要的是类型必须相同 . 以下是 (*) 的类型定义:

    λ> :t (*)
    (*) :: Num a => a -> a -> a
    

    但请注意 a 必须是同一类型,所以如果你部分地应用 Int

    λ> :t (* (4 :: Int))
    (* (4 :: Int)) :: Int -> Int
    

    它期望第二个参数和输出也是 Int .

    另一方面 (^) 的类型:

    λ> :t (^)
    (^) :: (Num a, Integral b) => a -> b -> a
    

    在两个可能不同类型的参数上工作,所以如果我们部分应用 Int 它将产生 Int ,但第二个参数仍然可以是任意 Integral

    λ> :t ((4 :: Int) ^)
    ((4 :: Int) ^) :: Integral b => b -> Int
    

    基本上每当你看到 a -> a -> a 时,这意味着类型变量 a 最终必须是同一类型,这就是为什么你不能将 IntFloat(*) 混合,尽管它们都安装在 Num 中 .

相关问题