#haskell
#haskell
Вопрос:
Вот мой код:
data Suit = Spade | Heart | Diamond | Club deriving (Eq, Show)
data CVal = Ace | King | Queen | Jack | Ten | Nine | Eight | Seven | Six | Five | Four | Three | Two deriving Show
data Card = Card Suit CVal deriving Show
sameSuit :: Card -> Card -> Bool
sameSuit (Card Spade _) (Card Spade _) = True
sameSuit (Card Heart _) (Card Heart _) = True
sameSuit (Card Diamond _) (Card Diamond _) = True
sameSuit (Card Club _) (Card Club _) = True
sameSuit (Card x _) (Card y _) = False
getNumber :: Card -> Int
getNumber (Card _ Two) = 2
getNumber (Card _ Three) = 3
getNumber (Card _ Four) = 4
getNumber (Card _ Five) = 5
getNumber (Card _ Six) = 6
getNumber (Card _ Seven) = 7
getNumber (Card _ Eight) = 8
getNumber (Card _ Nine) = 9
getNumber (Card _ Ten) = 10
getNumber (Card _ Jack) = 11
getNumber (Card _ Queen) = 12
getNumber (Card _ King) = 13
getNumber (Card _ Ace) = 14
beats :: Card -> Card -> Bool
beats x y = if sameSuit (x y) amp;amp; getNumber(x) > getNumber(y) then True else False
Сообщение об ошибке:
Couldn't match expected type `Bool' with actual type `Card -> Bool'
In the return type of a call of `sameSuit'
In the first argument of `(amp;amp;)', namely `sameSuit (x y)'
In the expression: sameSuit (x y) amp;amp; getNumber (x) > getNumber (y)
Я не понимаю, почему я не могу вызвать функцию «sameSuit» в finction «beats». Если я вызываю его из prelude, например prelude> sameSuit (Card Club 10) (Карточный клубный туз), он возвращает правильное значение, а тип функции — Bool, а не «Card -> Bool». Что я делаю не так? Кто-нибудь может мне это объяснить?
Комментарии:
1. В качестве отступления:
if blahblahblah then True else False
можно (и должно) сократить доblahblahblah
.2. Вы можете написать
sameSuit
намного проще:sameSuit (Card x _) (Card y _) = x == y
.3. Если вы измените порядок конструкторов в
CVal
и производнуюOrd
вам не нужнаgetNumber
функция вbeats
, вы могли бы просто использоватьx > y
.
Ответ №1:
В beats
вы, похоже, пытаетесь вызвать несколько функций как function(args)
, используя C-подобный синтаксис. Haskell не использует этот синтаксис; функциональное приложение написано с использованием простой смежности токенов, с круглыми скобками, необходимыми только для вложенных выражений.
getNumber(x)
безвредно, но бессмысленно. Это анализируется как применение функции getNumber
к выражению, заключенному в скобки (x)
, что, конечно, эквивалентно just getNumber x
, поэтому оно делает то, что вы хотите.
sameSuit (x y)
анализируется как применение функции sameSuit
к единственному аргументу, выражению в скобках (x y)
. Подвыражение, в свою очередь, является применением функции x
к y
, что не имеет смысла в данном контексте, поскольку x
является Card
, а не функцией. Вам нужно указать два аргумента для sameSuit
, как в sameSuit x y
.
Поскольку sameSuit
имеет тип Card -> Card -> Bool
, sameSuit
предоставляется только один аргумент типа Card -> Bool
. Об этой ошибке сообщает вам компилятор; вы, очевидно, не можете amp;amp;
использовать функцию и Bool
.
Если бы компилятор проверял вещи в другом порядке, он также сообщил бы вам, что это x y
не тип Card
, и это x
не функция.
Ответ №2:
Исправленная реализация beats
является:
beats x y = (sameSuit x y) amp;amp; (getNumber x > getNumber y)
Итак, вы можете вызвать sameSuit
in beats
, но вы должны использовать скобки.
Редактировать: На самом деле, вам не нужны скобки. В вашем коде вы вызывали sameSuit (x y)
, но вы должны вызывать его без скобок: sameSuit x y
Комментарии:
1. Никогда, никогда не записывайте
if c then True else False
,if
это полностью избыточно. Записьc
.