不能在< - “中使用where块?

时间:2018-06-10 10:40:52

标签: haskell where-clause

我基本上是在工作目录的“res”文件中定义给定文件的路径,我所做的如下:

iZone :: [Char]
iZone = "21.evt"

iZonePath :: String IO
iZonePath = result
 where
  path <- getCurrentDirectory
  result = (path ++ /res/ ++ iZone)

然而,ghc与

交流
  

src / Main.hs:15:8:错误:

parse error on input ‘<-’

Perhaps this statement should be within a 'do' block?    | 15 |   
     

路径&lt; - getCurrentDirectory

这是什么原因?我不能在“where”块中使用“&lt; - ”操作吗?

1 个答案:

答案 0 :(得分:3)

IO monad旨在强制程序员在副作用中选择特定的顺序。

假设允许这样做:

foo :: IO ()
foo = do
  putStrLn "1"
  putStrLn x
  putStrLn "2"
  putStrLn x
  putStrLn "3"
 where
  x <- putStrLn "x generated here" >> return "x used here"

输出是什么?

在打印x generated here之前,do块的最开头是否打印了1?就在那之后?

x generated here打印一次还是两次?

如果它在开始时发生过一次,那么简单地编写

会更清楚
foo :: IO ()
foo = do
  x <- putStrLn "x generated here" >> return "x used here"
  putStrLn "1"
  putStrLn x
  putStrLn "2"
  putStrLn x
  putStrLn "3"

如果以后要执行,我们可以将其移至想要的位置。

如果它意味着要运行两次,我们可以写

foo :: IO ()
foo = do
  x1 <- generateX
  putStrLn "1"
  putStrLn x1
  putStrLn "2"
  x2 <- generateX
  putStrLn x2
  putStrLn "3"
 where
  generateX = putStrLn "x generated here" >> return "x used here"

(或者,为了更具可读性,请使用let代替where

在上面的代码中,很明显generateX在精确点上运行了两次。

允许where x <- ...会导致执行不清楚。相反,do会使其变得精确。

实际上,do块的整个语法可以根据monadic操作>>=return进行重写,这保证了IO操作的明确排序。

原则上,人们可以扩展Haskell并定义where x <- ...,至少在某些情况下允许它,但似乎没有什么可以做到这一点,以及丢失代码清晰度的东西。

相关问题