Рекурсивное преобразование 3-х кортежей в символ - Haskell - PullRequest
0 голосов
/ 14 октября 2018

Учитывая эту функцию, мне было интересно, как можно решить эту проблему

convertChar' :: [[(Int, Int, Int)]] -> [[Char]] 

У меня есть следующие вспомогательные функции, не уверен, нужны ли они

toList :: [[(Int, Int, Int)]] -> [(Int, Int, Int)]
toList [(x)] = (x)

convertList :: [(Int, Int, Int)] -> [[(Int, Int, Int)]]
convertList x = [x] 

The (Int, Int, Int) будет либо (1, 1, 1) or (0, 0, 0)

  • Если кортеж равен (1, 1, 1), он вернет █ символ.
  • Если кортеж равен (0, 0, 0), он вернет ""

Мне было интересно, каков разумный подход к этому.Должен ли я преобразовать исходный ввод из [[()]] в [()] Применить функции, а затем преобразовать обратно в [[()]] перед повторным вызовом функции convertChar?

1 Ответ

0 голосов
/ 14 октября 2018

Лучший ответ, который я могу придумать, заключается в том, что вам, вероятно, следует изменить свою программу так, чтобы ваши типы представляли то, что вы хотите.В частности, когда я смотрю на ваш код, кажется, что у вас есть (или, по крайней мере, вы думаете / у вас нет, но вы написали не ту программу):

  1. Каждый [[(Int,Int,Int)]] представляет собой списокформа [xs]
  2. Каждый (Int,Int,Int) является либо (0,0,0), либо (1,1,1)

Во-первых, я запишу решение вашей проблемы, как указано.Во-вторых, я покажу вам, как создавать типы, которые представляют состояние мира (и не позволяют вам представлять недопустимые состояния).

renderThing (0,0,0) = ' '
renderThing (1,1,1) = '█'
renderState = map (map renderThing)

Давайте кратко опишем это.Первые две строки определяют частичную функцию для выполнения функции int-triple-to-char, как описано в родительском элементе.

Третья строка определяет требуемую функцию.Давайте прочитаем его слева направо:

  1. К renderState (который будет иметь тип [[(Int,Int,Int)]] -> [[Char]]):
  2. Примените map renderThing :: [(Int,Int,Int)] -> [Char] к каждому элементу списка, переданному какinput
    1. Чтобы выполнить эту функцию, примените renderThing к каждому элементу внутреннего списка (я предполагаю, что это строка)

К сожалению, ваша программа будетсбой, если вы когда-нибудь нарушите свой неявный инвариант, что любой (Int,Int,Int) равен либо (0,0,0), либо (1,1,1).Один лучший тип может быть (Bool,Bool,Bool), поскольку каждый элемент может иметь только одно из двух значений.Еще один способ сделать это:

data Thing = White | Black

Есть два способа вставить это в вашу программу.Либо используйте хорошие типы везде, чтобы компилятор мог убедиться, что вы никогда не попадете в непредвиденное состояние, либо у вас могут быть функции преобразования, которые могут иметь ошибки:

renderableBoard :: [[(Int,Int,Int)]] -> Either String [[Thing]]
renderableBoard = mapM (mapM convertOne) where
  convertOne (0,0,0) = White
  convertOne (1,1,1) = Black
  convertOne x = "cannot concert to thing: " ++ show x
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...