我不明白这种类型错误:
Couldn't match expected type `[t0]' with actual type `IO ()'
In the return type of a call of `printv'
In a stmt of a 'do' expression: px <- printv x
In the expression:
do { px <- printv x;
sep <- print ", ";
rest <- prints xs;
return (px : sep : rest) }
发件人:
data Value = IntValue Int
| TruthValue Bool
deriving (Eq, Show)
printv :: Value -> IO()
printv (IntValue i) = print i
printv (TruthValue b) = print ("boolean" ++ show b)
prints :: [Value] -> [IO()]
prints [] = []
prints (x:xs) = do px <- printv x
sep <- print ", "
rest <- prints xs
return (px:sep:rest)
我认为每个元素(px
)都会转换为IO()
操作,然后将其添加到相同内容的列表中,从而生成[IO()]
列表
我在这里缺少什么?通过删除打印件将其转换为字符串列表,可以正常工作。
答案 0 :(得分:3)
您错过了return
[]
prints
案例中的prints [] = return []
:
[()]
然而,你的版画很奇怪。它返回print
,因为printv
正在向控制台输出字符串,而不是返回它们。
您的意思是从import Text.PrettyPrint
import Data.List
data Value
= VInt Int
| VBool Bool
deriving (Eq, Show)
class Pretty a where
pretty :: a -> Doc
instance Pretty Value where
pretty (VInt i) = int i
pretty (VBool b) = text "Boolean" <+> text (show b)
draw :: [Value] -> String
draw = intercalate ", " . map (render.pretty)
main = putStrLn $ draw [VInt 7, VBool True, VInt 42]
函数返回字符串吗?
由于您正在尝试打印一个语法树,所以这是大致正确的方法:
像这样:
*A> main
7, Boolean True, 42
运行它:
{{1}}
答案 1 :(得分:2)
仔细查看您的功能类型:
prints :: [Value] -> [IO()]
但是如果我们现在看一下prints [] = []
,这是不匹配的,因为那个的类型是
prints :: [t] -> [a]
因此,您错过了使用prints [] = return []
,以使其正常运行。
答案 2 :(得分:1)
如果您没有评估IO操作,则不需要do
阻止。只需将IO ()
视为普通类型。
prints (x:xs) = printv x : print ", " : prints xs
答案 3 :(得分:1)
您不希望prints
返回IO操作数组。您希望它返回单个IO操作,该操作表示绑定在一起的每个IO操作。类似的东西:
prints xs = mapM_ (\x -> printv x >> putStr ", ") xs
除了我认为新行不会在你想要的地方结束。
有关详情,请查看mapM
和sequence
的{{3}}。特别是,序列的documentation可能与您尝试的类似。
但是,我真的建议在IO函数中完成所有工作,你应该编写一个纯函数来渲染你想要的文本格式,然后打印出来。特别是,Show
的{{1}}实例似乎是合适的。
Value
这样您就可以拨打instance Show Value where
show (IntValue i) = show i
show (TruthValue b) = "boolean " ++ show b
而不是print value
,如果您真的想要,可以按如下方式定义printv value
。
prints