代码之家  ›  专栏  ›  技术社区  ›  Wireless

Haskell Custom Show实例

  •  0
  • Wireless  · 技术社区  · 8 年前

    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

    1 回复  |  直到 8 年前
        1
  •  1
  •   Fyodor Soikin    8 年前

    表达式 map show 是一个需要类型为的参数的函数 [a] -因为 map 获取函数和列表。

    因此,表达式 (unwords . map show) 而且 需要类型为的参数的函数 [a] .

    因此,表达式 map (unwords . map show) 是一个需要类型为的参数的函数 [[a]] -它需要一个列表,其中每个元素也是一个列表,因为它必须是函数的可接受参数 (unwords。地图显示) .

    因此,在表达式中 map (unwords . map show) b ,最后一个参数 b 必须是类型 [a]] 对于一些人来说 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 s、 我把它留给读者作为练习。