2015-06-15 3 views
1

Итак, у меня есть эта функция, которая выравнивает текст влево для заданной ширины столбца. Я уже исправил некоторые из его проблем, но я не могу заставить его не использовать декрементированный параметр после его вызова, но вернуться к стартовому значению n. Вот мой код:Сокращенное значение, указанное в рекурсии в Haskell

f n s 
    | length s <= n = take (length s) s ++ "\n"      
    | n >= (maximum . map length . words) s =     
     if s !! n == ' ' || s !! n == '\t' || s !! n == '\n' 
     then take n s ++ "\n" ++ f n (drop (n+1) s)     
     else f (n - 1) s   --Here once called for some n-1 it proceeds to call it from then on only for it or even smaller n 
    | otherwise = error "Try bigger width!" 

Вот пример, где to на последней строке должно быть действительно на второй линии:

*Main> let s = "This miscellaneous items are starting to get shitty ." 
*Main> putStr $ f 22 s 
This miscellaneous 
items are starting 
to get shitty . 

Любые идеи?

+2

Какова цель 'take (length s) s ++" \ n "', когда вы могли бы просто выполнить 's ++" \ n "'? – rubik

ответ

2

Да, как только вы вызываете снова f с новым значением n, у него нет способа ссылаться на старое значение n, если вы не передадите его явно. Один из способов сделать это - иметь внутреннюю рекурсивную функцию с ее параметром width, как и у вас, но при необходимости может ссылаться на параметр на внешнюю функцию. Например, как-то так работает:

f n s = f' n s 
    where 
    f' width s 
     | length s <= width = s ++ "\n" 
     | n >= (maximum . map length . words) s = 
      if s !! width == ' ' || s !! width == '\t' || s !! width == '\n' 
      then take width s ++ "\n" ++ f' n (drop (width+1) s) 
      else f' (width - 1) s 
     | otherwise = error "Try bigger width!" 

Здесь width является текущей шириной в расчете, и n всегда изменяется, что позволяет f' использовать его при сбросе вычисления в начале новой строки.

Это только ответ на ваш точный вопрос. Хорошим упражнением было бы переписать ваш код в том, что было бы более идиоматичным Haskell, избегая некоторых ошибок производительности, таких как overreliance на !!. Но сначала заработайте, а затем сделайте его изящным!

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