Можно ли использовать `let in` в предложении экземпляра? - PullRequest
1 голос
/ 11 марта 2019
import Prelude hiding (Either (..))

data Tree a = Empty | Node a (Tree a) (Tree a)

instance Show a => Show (Tree a) where
  show t = show ST t

data ShowableTree a = ST Int (Tree a)

instance Show a => Show (ShowableTree a) where
  let
    indent 0 = ""
    indent n = "\t" ++ (indent n-1)
  in
    show (ST depth Empty) = (indent depth) ++ "()"
    show (ST depth (Node n l r)) =
      let
        stl = ST (depth+1) l
        str = ST (depth+1) r
      in
        (indent depth) ++ "(\n" ++ (indent depth) ++ (show n) ++ "\n" ++ (show stl) ++ "\n" ++ (show str) ++ "\n" ++ (indent depth) ++ ")\n"

Это выдает ошибки:

[m@green09 ~]$ ghci labn.hs
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 1] Compiling Main             ( labn.hs, interpreted )

labn.hs:14:3:
    parse error (possibly incorrect indentation or mismatched brackets)
Failed, modules loaded: none.

Давайте попробуем where возможно?

instance Show a => Show (ShowableTree a)
  where
    show (ST depth Empty) = (indent depth) ++ "()"
    show (ST depth (Node n l r)) =
      let
        stl = ST (depth+1) l
        str = ST (depth+1) r
      in
        (indent depth) ++ "(\n" ++ (indent depth) ++ (show n) ++ "\n" ++ (show stl) ++ "\n" ++ (show str) ++ "\n" ++ (indent depth) ++ ")\n"
    where
      indent 0 = ""
      indent n = "\t" ++ (indent n-1)

Все еще не удалось:

[m@green09 ~]$ ghci labn.hs
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 1] Compiling Main             ( labn.hs, interpreted )

labn.hs:19:5: parse error on input `where'
Failed, modules loaded: none.

Одним из четких решений является загрязнение глобальной области видимости путем перемещения определения indent в глобальную область действия.

Однако, за исключением этого, возможно ли как-то определить indent в ShowableTree?

1 Ответ

6 голосов
/ 11 марта 2019

Тело объявления экземпляра не является произвольным выражением;это список определений функций.let можно использовать только тогда, когда ожидается выражение, а where должно быть связано с одним уравнением.Тем не менее, достаточно просто определить show с помощью одного уравнения, которое позволит вам использовать либо.

-- using where
instance Show a => Show (ShowableTree a) where
    show (ST depth t) = case t of
                         Empty -> indent depth ++ "()"
                         Node n l r -> let stl = ST (depth + 1) l
                                           str = ST (depth + 1) r
                                       in  indent depth ++ "(\n" ++ indent depth ++ show n ++ "\n" ++ show stl ++ "\n" ++ show str ++ "\n" ++ indent depth ++ ")\n"
        where indent = flip replicate '\t'

-- using let
instance Show a => Show (ShowableTree a) where
    show (ST depth t) = let indent = flip replicate '\t'
                        in case t of
                             Empty -> indent depth ++ "()"
                             Node n l r -> let stl = ST (depth + 1) l
                                               str = ST (depth + 1) r
                                           in  indent depth ++ "(\n" ++ indent depth ++ show n ++ "\n" ++ show stl ++ "\n" ++ show str ++ "\n" ++ indent depth ++ ")\n"
...