Text Haskell:递归问题

Text Haskell:递归问题,text,haskell,recursion,justify,Text,Haskell,Recursion,Justify,我试图将文本格式化为矩形;目前,我已经能够得到正确的左对齐,但最后一行没有尽可能延伸 我试图计算出最佳的场宽度,以尽量减少或完全消除这一点 我完全卡住了。下面的代码显示了相关功能。现在它陷入了一个无限循环。 我哪里做错了 另一方面,调试Haskell代码的最佳方法是什么? (是的,我对这个很陌生。) optimumFieldWidth应该比较行的长度,直到顶行的长度等于底行的长度,然后返回导致此结果为真的字段宽度 module Main where import System import D

我试图将文本格式化为矩形;目前,我已经能够得到正确的左对齐,但最后一行没有尽可能延伸

我试图计算出最佳的场宽度,以尽量减少或完全消除这一点

我完全卡住了。下面的代码显示了相关功能。现在它陷入了一个无限循环。 我哪里做错了

另一方面,调试Haskell代码的最佳方法是什么? (是的,我对这个很陌生。)

optimumFieldWidth应该比较行的长度,直到顶行的长度等于底行的长度,然后返回导致此结果为真的字段宽度

module Main where

import System
import Data.List

main = do 
  (f:_) <- getArgs
  xs <- getContents
  putStr (show (bestFieldWidth maxLineLength xs))

bestFieldWidth :: Int -> String -> Int
bestFiledWidth _ [] = 0
bestFieldWidth lineLength xs
  | length (last input) == length (head input) = lineLength
  | otherwise = bestFieldWidth (length (head (rect (lineLength-1) xs))) xs
  where input = lines xs

rect :: Int -> String -> [String]
rect _ [] = []
rect lineLength xs
  | length input <= len = [input]
  | otherwise           = take len input : rect len (drop len input)
  where input = trim xs
        len   = bestFieldWidth lineLength xs

maxLineLength :: Int
maxLineLength = 40
modulemain其中
导入系统
导入数据。列表
main=do
(f:uu)Int
bestFiledWidth[]=0
bestFieldWidth线宽xs
|长度(上次输入)=长度(头部输入)=线宽
|否则=bestFieldWidth(长度(head(rect(lineLength-1)xs)))xs
其中输入=行xs
rect::Int->String->[String]
矩形[]=[]
直线长度

|长度输入在对
区域的后续调用中,
length(last input)==length(head input)
一次为false的条件似乎永远不会变为true,因此,使此函数始终采用
否则
分支,并使用相同的
xs
值无限期地调用自身,从而使用
输入


可能的原因是您使用了
lines
函数,该函数使用换行符拆分字符串,其方式不依赖于
lineLength
,并且与
rect
函数中的行拆分不一致。

似乎条件
长度(上次输入)=长度(头部输入)
一旦false,在随后对
区域的调用中就永远不会变为真,从而使此函数始终采用
否则
分支,并使用相同的
xs
值无限期地调用自己,从而
输入


可能的原因是您使用了
函数,该函数使用换行符拆分字符串,其方式不依赖于
行长度
,并且与
rect
函数中的行拆分不一致。

在回答您的旁注时,以下是调试Haskell的优秀指南:

还有Debug.Trace,它允许您插入打印语句。当然,它只能在调试时使用,因为它会使函数产生副作用


为了回答您的旁白,这里有一个调试Haskell的优秀指南:

还有Debug.Trace,它允许您插入打印语句。当然,它只能在调试时使用,因为它会使函数产生副作用


我想我应该把实际的解决方案放在这里,以防其他疯子想这样做。 请记住,它是由一个白痴写的,所以它可能不是最优雅的解决方案

maxFieldWidth :: Int
maxFieldWidth = 30

rect :: String -> String
rect xs  = (unlines (chunk (bestFieldWidth (maxFieldWidth) (lines input)) input))
  where input = itemsReplace '\n' ' ' xs

--Should be called with the point maximum desired width as n
bestFieldWidth :: Int -> [String] -> Int
bestFieldWidth _ [] = error "bestFieldWidth: Empty List"
bestFieldWidth n xs
  | n == 6 = 6
  | 1 == (length (last input)) = n
  | otherwise = (bestFieldWidth (n-1) xs)
  where input = chunk n (unlines xs)

chunk :: Int -> [a] -> [[a]]
chunk n [] = []
chunk n xs = ys : chunk n zs
  where (ys,zs) = splitAt n xs

itemsReplace :: Eq a => a -> a -> [a] -> [a]
itemsReplace _ _ [] = []
itemsReplace c r (x:xs)
  | c == x    = r:itemsReplace c r xs
  | otherwise = x:itemsReplace c r xs

我想我应该把实际的解决方案放在这里,以防其他疯子想这样做。 请记住,它是由一个白痴写的,所以它可能不是最优雅的解决方案

maxFieldWidth :: Int
maxFieldWidth = 30

rect :: String -> String
rect xs  = (unlines (chunk (bestFieldWidth (maxFieldWidth) (lines input)) input))
  where input = itemsReplace '\n' ' ' xs

--Should be called with the point maximum desired width as n
bestFieldWidth :: Int -> [String] -> Int
bestFieldWidth _ [] = error "bestFieldWidth: Empty List"
bestFieldWidth n xs
  | n == 6 = 6
  | 1 == (length (last input)) = n
  | otherwise = (bestFieldWidth (n-1) xs)
  where input = chunk n (unlines xs)

chunk :: Int -> [a] -> [[a]]
chunk n [] = []
chunk n xs = ys : chunk n zs
  where (ys,zs) = splitAt n xs

itemsReplace :: Eq a => a -> a -> [a] -> [a]
itemsReplace _ _ [] = []
itemsReplace c r (x:xs)
  | c == x    = r:itemsReplace c r xs
  | otherwise = x:itemsReplace c r xs

很抱歉我刚刚意识到这个名字是多么的错误。它应该比较行长,直到顶行的长度等于底行的长度,然后返回字段宽度,这会导致结果为真。@ratbum我已经更新了我的答案,以说明您添加的信息。对不起。我刚刚意识到这个名字是多么的错误。它应该比较行长,直到顶行的长度等于底行的长度,然后返回字段宽度,从而使其为真。@ratbum我已经更新了我的答案,以说明您添加的信息。