Образец, который вы используете для доски, является неполным. Модель [(h1,t1)]
будет только Соединительные доски с один элемент (пара (h1,t1)
).
Это то же самое, что с использованием рисунка (h1,t1):[]
, т.е. список (:
), содержащий элемент (h1,t1)
, за которым следует пустой список []
.
Если попытаться запустить свой код с примерами, которые Вы дали, (2,3)
и [(3,4), (5,6)]
(Примечание: Вы должны запятую между элементами списка!), То мы получим следующее:
goesP (2,3) [(3,4), (5,6)] LeftEnd
Haskell будет пытаться сопоставляйте эти аргументы с шаблонами вашего определения сверху донизу.
Он проверит следующий шаблон первый:
goesP (h,t) [(h1,t1)] LeftEnd
Первый и третий аргументы будут соответствовать, по «объединяющим» h
с 2
, t
с 3
и LeftEnd
с LeftEnd
, но второй будет не соответствовать , Аргумент [(3,4), (5,6)]
является «синтаксическим сахаром» для списка (3,4):(5,6):[]
, в то время как шаблон [(h1,t1)]
является синтаксическим сахаром для списка (h1,t1):[]
. Мы могли бы объединить h1
с 3
и t1
с 4
, но нет ничего, чтобы объединить (5,6)
с.
Haskell будет переходить к следующей возможности:
goesP (h,t) [(h1,t1)] RightEnd
Первый аргумент будет соответствовать (с h
как 2
и t
как 3
), но вторым аргументом не получится по той же причине, что и предыдущий пункт , Третий аргумент также не будет соответствовать, поскольку LeftEnd
и RightEnd
- разные значения (но это точка;)).
Haskell увидит, что возможностей больше нет, поэтому программа выйдет из строя.
Чтобы исправить это, вам необходимо изменить шаблоны для вторых аргументов, чтобы доски с несколькими домино обрабатывались должным образом.
Корпус для LeftEnd
довольно легко, просто изменить список одного элемента (h1,t1):[]
к списку по крайней мере, один элемент (h1,t1):_
(я также добавил дополнительный =
после otherwise
):
goesP (h,t) ((h1,t1):_) LeftEnd
| h==h1 || t==h1 = True
| otherwise = False
case for RightEnd
сложнее, так как мы хотим сравнить с последний элемент списка, но у нас только есть доступ к сперва. В этом случае мы можем сохранить ваше определение, которое проверяет одноэлементные списки, но также добавляет другое определение, которое использует рекурсию: если список содержит более одного элемента, удалите первый элемент и снова проверьте его. Таким образом, любой непустой список в конечном счете не будет разбит, пока он только один элемент, который существующий шаблон может работать (опять же, я добавил недостающий =
):
goesP (h,t) [(h1,t1)] RightEnd
| h==h1 || t==h1 = True
| otherwise = False
goesP (h, t) (_:xs) RightEnd = goesP (h, t) xs RightEnd
Теперь Haskell будет соответствовать [(3,4), (5,6)]
(который является сахаром для (3,4):(5,6):[]
) против (h1,t1):[]
. Это не удастся, так как списки имеют разную длину. Затем он будет соответствовать [(3,4), (5,6)]
против _:xs
, который преуспеет, объединив xs
с (5,6):[]
. Затем мы снова запускаем функцию, используя xs
. На этот раз (5:6):[]
будет унифицировать с помощью (h1,t1):[]
, чтобы мы могли проверить, равны ли эти числа или нет.
Кроме того, наблюдение: goesP
на самом деле слишком сложно. Вы используете «ограждения рисунка» для выбора между значением True
и значением False
; однако для защиты рисунков также требуется a Bool
для работы. Другими словами, такой код:
| h==h1 || t==h1 = True
| otherwise = False
Может быть прочитана как говорят «Создайте значение Bool
h==h1 || t==h1
, если это True
, то возвращение True
Если False
затем вернуться False
.»
Очевидно, что это является излишним: мы можем просто вернуть значение h==h1 || t==h1
:
goesP (h,t) ((h1,t1):_) LeftEnd = h==h1 || t==h1
goesP (h,t) [(h1,t1)] RightEnd = h==h1 || t==h1
goesP (h, t) (_:xs) RightEnd = goesP (h, t) xs RightEnd
UPDATE: Исправлена мой RightEnd код
Отформатируйте фрагмент кода, который вы предоставили (он должен выглядеть как 'this'). В настоящее время он почти не читается. Вы можете использовать backticks или четыре пробела отступа, чтобы получить этот эффект. Google для «уценки», чтобы узнать больше о правилах синтаксиса. –
@AndrewThaddeusMartin Или просто нажмите кнопку «help» при редактировании, он покажет вам весь синтаксис форматирования. – bheklilr
Кроме того, мы предпочитаем правильную грамматику и правописание на этом сайте. Я отредактировал сообщение на данный момент, но, пожалуйста, убедитесь, что вы правильно поняли его для будущих вопросов. Что касается этого, то до сих пор неясно, о чем вы говорите, «и конец как влево, так и вправо». – leftaroundabout