2014-10-19 2 views
0

Это мой код, который пытается проверить, может ли список быть париально идентичным в другом. Это игра в домино Domino=(Int,Int) и Board = [Domino], а конец - влево или вправо. Я должен проверить, если какой-либо домино входит в доску, например, может ли домино (2,3) войти в борт [(3,4)(5,6)] должен уметь идти влево, потому что (2,3) и (3,4) имеют аналогичный элемент. Вот мой кодКак проверить, являются ли два списка частично идентичными haskell

goesP :: Domino -> Board -> End -> Bool 

goesP (h,t) [(h1,t1)] LeftEnd 
     | h==h1 || t==h1 =True 
     | otherwise False 
goesP (h,t) [(h1,t1)] RightEnd 
     | h==t1 || t==t1 = True 
     | otherwise False 
+1

Отформатируйте фрагмент кода, который вы предоставили (он должен выглядеть как 'this'). В настоящее время он почти не читается. Вы можете использовать backticks или четыре пробела отступа, чтобы получить этот эффект. Google для «уценки», чтобы узнать больше о правилах синтаксиса. –

+2

@AndrewThaddeusMartin Или просто нажмите кнопку «help» при редактировании, он покажет вам весь синтаксис форматирования. – bheklilr

+0

Кроме того, мы предпочитаем правильную грамматику и правописание на этом сайте. Я отредактировал сообщение на данный момент, но, пожалуйста, убедитесь, что вы правильно поняли его для будущих вопросов. Что касается этого, то до сих пор неясно, о чем вы говорите, «и конец как влево, так и вправо». – leftaroundabout

ответ

1

Образец, который вы используете для доски, является неполным. Модель [(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 

Может быть прочитана как говорят «Создайте значение Boolh==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 код