haskell - 是否可以在实例子句中使用`let in`?
问题描述
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
within ShowableTree
?
解决方案
The body of an instance declaration is not an arbitrary expression; it's a list of function definitions. let
can only be used where an expression is expected, and where
has to be associated with a single equation. However, it's simple enough to define show
with a single equation that would allow you to use either.
-- 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"
推荐阅读
- python - 支持向量机 SVM python ValueError: X.shape[1]
- angular - Angular 4 - 不要为下拉列表中的特定选项更新 ngModel
- sql - DBMS 输出不显示
- c++ - 尝试验证 int 输入并拒绝小数和空格
- php - PHP "for loop" 标签,从 MySQL 数据库到 HTML Table
- c - 如何测试零是否已更改为一(但不是相反)
- javascript - Node.js Webshot 不适用于 PowerBI,因为 Phantom.js 不支持 WebGL
- java - 如何在 Jhipster 的前端使用 HashMap?
- php - 如何使用 ACF 返回 WordPress REST API 中的永久链接?
- find - 如何查找名称包含字符串的文件夹