2014-10-14 6 views
0

Я хочу, чтобы определить тип данных R как рациональные числа, где R представляет собой (знаменатель, числитель) и я определил, как:Haskell типов, определенный пользователь данные

data R = R {n::Int, 
      d::Int} deriving Show 

Теперь я попытался сделать функцию, которая принимает два аргумента (список R и R) и возвращает список с эквивалентами R. Я пробую это, но даю мне ошибку типов.

equivalentes' :: [R] -> R -> [R] 
equivalentes' [] _ = [] 
equivalentes' (x:xs) r 
    | (n x `mod` n r == 0) && (d x `mod` d r == 0) = (R(d n)x): equivalentes' xs r 
    | otherwise = equivalentes' xs r 

Моя идея заключается в том, чтобы вернуть что-то вроде этого:

> equivalentes'[R(2,4),R(3,5),R(4,8)] (R(1,2)) 
        [R (2,4),R (4,8)] 
+1

Какая ошибка? – Cirdec

+0

@Cirdec 'Не удалось сопоставить ожидаемый тип' R 'с фактическим типом 'R -> Int' ...' –

+2

Вы показали нам определение для функции с именем 'equales'' (с' '' в конце), но его реализация и ваш пример вызова относятся к 'equales' (без' ''). Где определение этой другой функции? – jwodder

ответ

5

проблема с выражением

R (d n) x : equivalentes' xs r 

И конкретно с

d n 

n фу nction имеет тип R -> Int, как и функция d, но вы прошли n до d в качестве аргумента. Может быть, вы имели в виду что-то вроде

R (d x) x 

Но поскольку x имеет тип R, это также не будет работать, так что вы можете иметь в виду

R (d x) (n x) 

или что-то подобное.


На другой ноте, вы не можете сделать R (1, 2), потому что (1, 2) является кортеж из двух Int с, а не только два отдельных Int с. вы могли бы сделать вместо этого R 1 2, или uncurry R (1, 2), если вы действительно хотели использовать кортежи.

+0

Тот факт, что такие ошибки трудно обнаружить, заключается в том, почему нельзя использовать однобуквенные имена для полей (или что-то еще в глобальном масштабе, если на то пошло). –

+0

@Rhymoid Я бы даже рассматривал это как дополнительную причину, почему вы этого не должны, но что более важно, вы должны использовать описательные имена, чтобы люди знали, что делает код с первого взгляда. Я предполагаю, что это могло быть вместо 'data Ratio = Ratio {числитель :: Int, знаменатель :: Int}', но только после просмотра кода, чтобы выяснить, что пытается сделать OP. Если бы подобные названия использовались для начала, не было бы путаницы. – bheklilr

3

В Haskell обе функции и конструкторы применяются путем сопоставления. Например, f x - это функция f, примененная к аргументу x. f x y - это функция f, применяемая к x, с результатом, применяемым к y. Вы можете думать о f x y как f применительно к двум аргументам, x и y. Вам не нужны скобки для применения функции или конструктора, например f (x y) означает что-то другое - в этом случае x применяется к y, а f (x, y) означает, что функция f применяется к кортежу (x, y).

Для вашего кода, вам нужно использовать

  • R 2 4 вместо R(2,4)
  • R (n x) (d x) вместо R(d n)x

Когда мы делаем эти изменения синтаксиса, equivalentes будет записана как

equivalentes :: [R] -> R -> [R] 
equivalentes [] _ = [] 
equivalentes (x:xs) r 
    | (n x `mod` n r == 0) && (d x `mod` d r == 0) = R (n x) (d x): equivalentes xs r 
    | otherwise = equivalentes xs r 

И ваш пример будет указан как

equivalentes [R 2 4,R 3 5,R 4 8] (R 1 2)