【问题标题】:Haskell Custom Show InstanceHaskell 自定义显示实例
【发布时间】:2017-11-22 18:58:46
【问题描述】:

我有一个问题,仍在研究家谱树,这是我目前得到的(抱歉葡萄牙语单词 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

所以,家庭的根是 Bob,Bob 的儿子是 John 和 Hank,John 有一个女儿叫 Ruth。

我已经尝试了几种方法来使用我在其他帖子中看到的东西,但这是最新的尝试:

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

【问题讨论】:

标签: haskell tree show


【解决方案1】:

表达式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

请注意,上述解决方案不会为您提供所需的结果,因为它不会在嵌套的Familias 之前插入缩进。我把它留给读者作为练习。

【讨论】:

  • 我觉得不错,谢谢,就一个问题,怎么去掉引号?尝试了一些东西,但无法从输出中删除它们
  • 引号来自show ashow 函数通常不是为了产生用户友好的输出,而是作为技术展示。因此,show 通常会生成有效的 Haskell 代码文本,或者至少非常接近它。具体来说,showing a String 会将字符串括在双引号中。为避免这种情况,只需直接使用a(因为它已经是String),而不是先通过show
  • 哦,谢谢 :D 抱歉我缺乏知识,仍然是 Haskell 世界的初学者 :p
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-07
  • 1970-01-01
相关资源
最近更新 更多