2015-12-19 4 views
0

Я пытаюсь сделать проблему 9 Project Euler прямо сейчас, но 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. 

То, что я не понимаю, почему (*) и (^) ожидают поплавки и Ints, когда проверка их ввода в ghci с :t показывает, что их аргументы нужно рассматривать только Nums.

+5

Тип '*' например: 'Num a => a -> a -> a' - вы правы, что он принимает любой экземпляр' Num', однако он принимает только один тип за раз, и возвращает тот же тип. Выражение 'x * y * z' имеет тип' Int', или оно не хорошо напечатано, потому что вы объявили 'x' иметь тип' Int'. Однако вы возвращаете float. Просто добавьте другой 'fromIntegral $ x * y * z'. – user2407038

+0

вам также нужно «закруглить» уравнение 'z', тогда вы можете установить тип результата на' Int' – epsilonhalbe

ответ

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 в конечном счете должен быть го один и тот же тип, вот почему вы не можете смешивать Int и Float с (*), несмотря на то, что оба они установлены в Num.

Смежные вопросы