Haskell 自定义显示实例
Haskell Custom Show Instance
我有一个问题,仍在研究家谱树,这是我目前得到的(抱歉是葡萄牙语 xD):
data Familia = Node String [Familia]
instance Show Familia where
show (Node a b) = show a ++ "\n\t" ++ show b
raiz :: String -> Familia
raiz n = (Node n [])
juntar :: String -> String -> Familia -> Familia
juntar a b (Node c l)
| b == c = (Node c (l ++ [raiz a]))
| otherwise = (Node c (juntarAux a b l))
juntarAux :: String -> String -> [Familia] -> [Familia]
juntarAux a b [] = []
juntarAux a b [(Node x l)]
| x == b = [(juntar a b (Node x l))]
| otherwise = [(Node x (juntarAux a b l))]
juntarAux a b ((Node x l):xs)
| x == b = (juntar a b (Node x l)):xs
| otherwise = (Node x l):(juntarAux a b xs)
这是我想要的方式,问题是,这是我当前的输出:
*Main> let f = raiz "Bob"
*Main> let g = juntar "John" "Bob" f
*Main> g
"Bob"
["John"
[]]
我想要的是,像这样打印它:
Bob
John
Ruth
Hank
所以,这个家庭的根是鲍勃,鲍勃的儿子是约翰和汉克,约翰有一个女儿叫露丝。
我已经尝试过用在其他帖子中看到的东西来做这件事,但这是最新的尝试:
instance Show Familia where
show (Node a b) = show a ++ "\n\t" ++ (unlines $ map (unwords . map show) b)
这给了我以下错误:
t4.hs:14:77:
Couldn't match type ‘Familia’ with ‘[a0]’
Expected type: [[a0]]
Actual type: [Familia]
In the second argument of ‘map’, namely ‘b’
In the second argument of ‘($)’, namely
‘map (unwords . map show) b’
有什么想法吗?提前致谢! :D
表达式 map show
是一个需要 [a]
类型参数的函数 - 因为 map
接受一个函数和一个列表。
因此,表达式 (unwords . map show)
也是 一个需要 [a]
.
类型参数的函数
因此,表达式 map (unwords . map show)
是一个需要类型为 [[a]]
的参数的函数 - 它需要一个列表,其中的每个元素也是一个列表,因为它必须是一个可接受的参数对于函数 (unwords . map show)
.
因此,在表达式 map (unwords . map show) b
中,对于某些 a
,最后一个参数 b
必须是 [[a]]
类型。
但是从模式 Node a b
可以看出 b
属于 [Familia]
类型 - 这与 [[a]]
不兼容。这是编译器在错误消息中告诉您的内容。
当您发现自己对嵌套函数的类型感到困惑时,将它们全部分开通常是个好主意,为每一部分命名(也可能是类型)。这样你就可以看出哪里出了问题。
instance Show Familia where
show (Node a b) = show a ++ "\n\t" ++ concatSubFamilias
where
showSubFamilias :: [String]
showSubFamilias = map show b
concatSubFamilias :: String
concatSubFamilias = unlines showSubFamilias
请注意,上述解决方案不会为您提供所需的结果,因为它不会在嵌套的 Familia
之前插入缩进。我把它留作 reader.
的练习
我有一个问题,仍在研究家谱树,这是我目前得到的(抱歉是葡萄牙语 xD):
data Familia = Node String [Familia]
instance Show Familia where
show (Node a b) = show a ++ "\n\t" ++ show b
raiz :: String -> Familia
raiz n = (Node n [])
juntar :: String -> String -> Familia -> Familia
juntar a b (Node c l)
| b == c = (Node c (l ++ [raiz a]))
| otherwise = (Node c (juntarAux a b l))
juntarAux :: String -> String -> [Familia] -> [Familia]
juntarAux a b [] = []
juntarAux a b [(Node x l)]
| x == b = [(juntar a b (Node x l))]
| otherwise = [(Node x (juntarAux a b l))]
juntarAux a b ((Node x l):xs)
| x == b = (juntar a b (Node x l)):xs
| otherwise = (Node x l):(juntarAux a b xs)
这是我想要的方式,问题是,这是我当前的输出:
*Main> let f = raiz "Bob"
*Main> let g = juntar "John" "Bob" f
*Main> g
"Bob"
["John"
[]]
我想要的是,像这样打印它:
Bob
John
Ruth
Hank
所以,这个家庭的根是鲍勃,鲍勃的儿子是约翰和汉克,约翰有一个女儿叫露丝。
我已经尝试过用在其他帖子中看到的东西来做这件事,但这是最新的尝试:
instance Show Familia where
show (Node a b) = show a ++ "\n\t" ++ (unlines $ map (unwords . map show) b)
这给了我以下错误:
t4.hs:14:77:
Couldn't match type ‘Familia’ with ‘[a0]’
Expected type: [[a0]]
Actual type: [Familia]
In the second argument of ‘map’, namely ‘b’
In the second argument of ‘($)’, namely
‘map (unwords . map show) b’
有什么想法吗?提前致谢! :D
表达式 map show
是一个需要 [a]
类型参数的函数 - 因为 map
接受一个函数和一个列表。
因此,表达式 (unwords . map show)
也是 一个需要 [a]
.
因此,表达式 map (unwords . map show)
是一个需要类型为 [[a]]
的参数的函数 - 它需要一个列表,其中的每个元素也是一个列表,因为它必须是一个可接受的参数对于函数 (unwords . map show)
.
因此,在表达式 map (unwords . map show) b
中,对于某些 a
,最后一个参数 b
必须是 [[a]]
类型。
但是从模式 Node a b
可以看出 b
属于 [Familia]
类型 - 这与 [[a]]
不兼容。这是编译器在错误消息中告诉您的内容。
当您发现自己对嵌套函数的类型感到困惑时,将它们全部分开通常是个好主意,为每一部分命名(也可能是类型)。这样你就可以看出哪里出了问题。
instance Show Familia where
show (Node a b) = show a ++ "\n\t" ++ concatSubFamilias
where
showSubFamilias :: [String]
showSubFamilias = map show b
concatSubFamilias :: String
concatSubFamilias = unlines showSubFamilias
请注意,上述解决方案不会为您提供所需的结果,因为它不会在嵌套的 Familia
之前插入缩进。我把它留作 reader.