2015-01-20 2 views
1

Answersexist для как к довольно-печати в Haskell, в том числе, как это сделать с packages, но это скорее вопрос о том, почему мой первый подход потерпел неудачу.Довольно-печать 2D список в Haskell (Объяснение Failure)

Учитывая 2D список вида w = [r,r1,r2], где W, R являются соответствующих типов данных w::W, r::R (простые вары для примера, а не мое фактическое соглашение об именовании):

data X = Y | Z 
     deriving (Eq, Show) 

data R = [X] 
     deriving (Eq, Show) 

data W = [R] 
     deriving (Eq, Show) 

Почему бы не работает один из следующих подходов? (Я полностью осознаю это будет включать в скобки и запятые, что это не проблема)

ppR :: R -> IO() 
ppR = putStrLn . show 

и либо

ppW :: W -> IO W (?) 
ppW (w:[]) = ppR w 
ppW (w:ws) = ppR w >> ppW ws 

или

ppW :: W -> IO W (?) 
ppW (w:[]) = putStrLn . show w 
ppW (w:ws) = putStrLn . show w >> ppW ws 

Я не совсем знаю, типы ppW, я все еще учусь. В дополнение к моему явному наивному (недостатку) пониманию того, как Haskell справляется с нечистыми функциями, меня также сбивает с толку тот факт, что второй подход к ppW typechecks (без заданного типа).

Почему этот подход не работает? Не можете ли вы рекурсивно распечатать двумерный список неопределенной длины в Haskell?

ответ

2

В вашем случае тип должен быть ppW :: W -> IO(). () (произносится как «единица») - это тип, который может иметь только одно значение *, а именно (). Таким образом, IO() - это действие IO, которое в результате не дает значения (это эквивалентность функций void от C, C++ или Java).

Вот некоторые кусок кода, который должен составлять:

data X = Y | Z 
    deriving (Eq, Show) 

type R = [X] 

type W = [R] 

ppR :: R -> IO() 
ppR = putStrLn . show 

ppW :: W -> IO() 
ppW (w:[]) = ppR w 
ppW (w:ws) = ppR w >> ppW ws 

Если у вас есть какие-либо проблемы с типами вы всегда можете использовать GHCI, чтобы определить тип какой-либо функции. Или вы можете просто посмотреть на типы функций, которые вы используете:

putStrLn :: String -> IO() 
(>>) :: IO a -> IO b -> IO b -- this is not exactly what ghci would tell you. 

Edit: В коде я включил я type вместо data. type определяет синоним типа (это похоже на C/C++ typedef). Это проще использовать их, чем использовать data - data требует, чтобы вы явно выписывать имя конструктора, так что вы бы:

data R = R [X] 

ppR :: R -> IO() 
ppR (R r)= putStrLn (show r) 

* на самом деле это может быть также и снизу, но это другая история.

+2

Я думаю, что это заслуживает объяснения, почему вместо 'data' используется' type'. ('R' и' W' не имеют конструкторов) – Cirdec

+1

Это облегчение, чтобы знать, что я на самом деле не был слишком далеко. Я отмечу это как принято, как только смогу пойти домой и попробовать это сам. – Andy

Смежные вопросы