Is it possible to use `let in` in an instance clause?

gaa*_*kam 1 haskell compiler-errors syntax-error

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"
Run Code Online (Sandbox Code Playgroud)

This spits out errors:

[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.
Run Code Online (Sandbox Code Playgroud)

Let's try where perhaps?

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)
Run Code Online (Sandbox Code Playgroud)

Still no success:

[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.
Run Code Online (Sandbox Code Playgroud)

One clear solution is to pollute the global scope by moving the definition of indent to the global scope.

Barring this, however, is it possible to somehow define indent within ShowableTree?

che*_*ner 6

实例声明的主体不是任意表达式;这是函数定义的列表。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"
Run Code Online (Sandbox Code Playgroud)