相关疑难解决方法(0)

Template Haskell有什么不好的?

似乎模板Haskell经常被Haskell社区视为一种​​不幸的便利.我很难准确地说出我在这方面所观察到的内容,但请考虑这几个例子

我已经看过各种博客文章,其中人们使用模板Haskell做了相当简洁的东西,实现了更好的语法,这在常规的Haskell中是不可能的,以及巨大的样板减少.那么为什么模板Haskell以这种方式受到鄙视呢?是什么让它不受欢迎?在什么情况下应避免模板Haskell,为什么?

haskell template-haskell

249
推荐指数
6
解决办法
2万
查看次数

withFile与openFile

当给定由\n分隔的文本输入文件时,此程序产生我期望的输出:

import System.IO

main :: IO ()
main = do h <- openFile "test.txt" ReadMode 
          xs <- getlines h
          sequence_ $ map putStrLn xs

getlines :: Handle -> IO [String]
getlines h = hGetContents h >>= return . lines
Run Code Online (Sandbox Code Playgroud)

用withFile代替openFile并稍微重新排列

import System.IO

main :: IO ()
main = do xs <- withFile "test.txt" ReadMode getlines
          sequence_ $ map putStrLn xs

getlines :: Handle -> IO [String]
getlines h = hGetContents h >>= return . lines  
Run Code Online (Sandbox Code Playgroud)

我设法完全没有输出.我很难过.

编辑:不再难过了:感谢一个人和所有人的深思熟虑和发人深省的答案.我在文档中做了一些阅读,并了解到withFile可以理解为支架 …

haskell

27
推荐指数
4
解决办法
6510
查看次数

Haskell:Lazy vs. Strict Text值,推荐哪一个?

我在Data.Text上做了很多阅读,但是我还没有找到什么时候更喜欢Strict over Lazy,反之亦然.

我的理解是Data.Text.Strict是内存中连续字符的数据结构,而Data.Text.Lazy是一块连续的字符.

我的问题是为什么我不应该总是使用Data.Text.Lazy?似乎唯一的开销是块管理,但我不知道它是否足够明显?作为交换,当Text值变大时,连接操作可以便宜得多.

欢迎思考和见解!

text haskell

13
推荐指数
2
解决办法
1071
查看次数

在Haskell中流式传输目录的递归下降

我正在尝试使用Haskell进行目录结构的递归下降.我想只根据需要检索子目录和文件(懒惰).

我编写了以下代码,但是当我运行它时,跟踪显示在第一个文件之前访问了所有目录:

module Main where

import Control.Monad ( forM, forM_, liftM )
import Debug.Trace ( trace )
import System.Directory ( doesDirectoryExist, getDirectoryContents )
import System.Environment ( getArgs )
import System.FilePath ( (</>) )

-- From Real World Haskell, p. 214
getRecursiveContents :: FilePath -> IO [FilePath]
getRecursiveContents topPath = do
  names <- getDirectoryContents topPath
  let
    properNames =
      filter (`notElem` [".", ".."]) $
      trace ("Processing " ++ topPath) names
  paths <- forM properNames $ \name -> do
    let path = topPath …
Run Code Online (Sandbox Code Playgroud)

haskell directory-structure lazy-evaluation

11
推荐指数
2
解决办法
1938
查看次数

为什么序列[getLine,getLine,getLine]的计算没有被延迟?

main = do
  input <- sequence [getLine, getLine, getLine]
  mapM_ print input
Run Code Online (Sandbox Code Playgroud)

让我们看看这个程序的实际效果:

m@m-X555LJ:~$ runhaskell wtf.hs
asdf
jkl
powe
"asdf"
"jkl"
"powe"
Run Code Online (Sandbox Code Playgroud)

令我惊讶的是,这里似乎没有懒惰。取而代之getLine的是,急切地评估所有3个值,将读取的值存储在内存中,然后而不是在此之前将所有值打印出来。

比较一下:

main = do
  input <- fmap lines getContents
  mapM_ print input
Run Code Online (Sandbox Code Playgroud)

让我们看一下实际情况:

m@m-X555LJ:~$ runhaskell wtf.hs
asdf
"asdf"
lkj
"lkj"
power
"power"
Run Code Online (Sandbox Code Playgroud)

完全不同的东西。行被一一读取并一一打印。这对我来说很奇怪,因为我看不到这两个程序之间有什么区别。

从LearnYouAHaskell:

当I / O操作所使用,sequenceA是同样的事情sequence!它获取I / O操作的列表,并返回将执行这些操作中的每个操作的I / O操作,并以结果的形式列出这些I / O操作的结果。这是因为要将一个[IO a]值转换为一个IO [a]值,以使一个I / O操作在执行时产生结果列表,所以所有这些I / O操作都必须先进行排序,以便在评估时依次执行。被迫。如果不执行I / O操作,则无法获得结果。

我糊涂了。我不需要执行所有IO操作就可以得到一个结果。

该书前面几段显示了以下内容的定义sequence

sequenceA :: …
Run Code Online (Sandbox Code Playgroud)

recursion haskell sequence lazy-evaluation

8
推荐指数
1
解决办法
79
查看次数

在readFile之后Haskell文件会自动关闭吗?

我想使用Haskell函数

readFile :: FilePath -> IO String
Run Code Online (Sandbox Code Playgroud)

将文件的内容读入字符串.在文档中,我读到"文件是按需读取的,与getContents一样."

我不确定我完全理解这一点.例如,假设我写

s <- readFile "t.txt"
Run Code Online (Sandbox Code Playgroud)

执行此操作时:

  • 该文件已打开.
  • s中的字符实际上是从文件中读取的,但是需要它们来评估某些表达式(例如,如果我评估文件的length s 所有内容将被读取并且文件将被关闭).
  • 一旦读取了最后一个字符,readFile就会关闭与此调用相关联的文件句柄(自动).

我的第三个陈述是否正确?那么,我可以在readFile不关闭文件句柄的情况下调用吗?只要我没有消耗(访问)整个结果字符串,句柄是否会保持打开状态?

编辑

以下是有关我的疑虑的更多信息.假设我有以下内容:

foo :: String -> IO String
foo filename = do
                  s <- readFile "t.txt"
                  putStrLn "File has been read."
                  return s
Run Code Online (Sandbox Code Playgroud)

putStrLn执行时,我会(直觉地)期望

  1. s包含文件的全部内容t.txt,
  2. 用于读取文件的句柄已关闭.

如果不是这样的话:

  • 什么s时候putStrLn执行包含什么?
  • putStrLn执行时文件句柄处于什么状态?
  • 如果putStrLn执行的时间s不包含文件的全部内容,实际上何时会读取此内容,何时关闭文件?

io haskell lazy-evaluation

7
推荐指数
2
解决办法
1504
查看次数

如何提高Haskell IO的性能?

似乎Haskell的IO相对较慢.

例如,将Haskell与Python进行比较

#io.py
import sys
s=sys.stdin.read()
sys.stdout.write(s)
Run Code Online (Sandbox Code Playgroud)

,

-- io.hs
main = do
    s <- getContents
    putStr s
Run Code Online (Sandbox Code Playgroud)

他们的表现(gen.py将512k数据写入stdout):

Python版本:

$ time python gen.py | python io.py > /dev/null

real    0m0.203s
user    0m0.015s
sys     0m0.000s
Run Code Online (Sandbox Code Playgroud)

Haskell版本:

$ time python gen.py | runhaskell io.hs > /dev/null

real    0m0.562s
user    0m0.015s
sys     0m0.000s
Run Code Online (Sandbox Code Playgroud)

似乎Haskell的价格要低得多.我的测试有问题吗?或者它只是Haskell的固有问题?

谢谢.

io haskell

7
推荐指数
1
解决办法
541
查看次数

在Haskell中读取大型二进制文件的最快方法?

我想处理一个太大而无法读入内存的二进制文件。目前,我使用ByteString.Lazy.readFile来流传输字节。我认为使用流媒体包来提高程序速度是一个好主意。但是,的文档显示readFile

readFile :: FilePath -> (Stream (Of String) IO () -> IO a) -> IO a

使用类型为'Stream(Of String)IO()-> IO a'的函数读取文件的行,以将流转换为'IO a'类型的值。

所以streaming包只读取ASCII文本文件?我可以使用该程序包以字节为单位读取二进制文件吗?

haskell

7
推荐指数
1
解决办法
178
查看次数

haskell中的懒惰IO:如何返回由某些阻塞的IO生成的惰性列表?

getText = do
    c <- getChar
    s <- getText
    return (c : s)

main = do
    s <- getText
    putStr s
Run Code Online (Sandbox Code Playgroud)

我期望看到的是每次按下'Enter'后输入线都会被回显.但没有任何回应...(我知道这是一个无限循环)它似乎不会" return"直到它上面的所有"IO"执行....

但是,以下代码:

main = do
    s <- getContents
    putStr s
Run Code Online (Sandbox Code Playgroud)

它在输入后立即显示该行.

鉴于功能getChar,我可以写一个getText表现得像getContents

haskell lazy-evaluation

3
推荐指数
2
解决办法
298
查看次数

从hGetContents中检测惰性字符串中的I/O异常?

hGetContents返回一个惰性String对象,该对象可用于纯函数代码以从文件句柄中读取.如果在读取此延迟字符串时发生I/O异常,则会以静默方式关闭基础文件句柄,并且不会向延迟字符串添加其他字符.

如何检测此I/O异常?

作为一个具体的例子,考虑以下程序:

import System.IO    -- for stdin

lengthOfFirstLine :: String -> Int
lengthOfFirstLine "" = 0
lengthOfFirstLine s  = (length . head . lines) s

main :: IO ()
main = do
    lazyStdin <- hGetContents stdin
    print (lengthOfFirstLine lazyStdin)
Run Code Online (Sandbox Code Playgroud)

如果在读取文件的第一行时发生异常,则此程序将打印字符数,直到发生I/O异常.相反,我希望程序崩溃并使用适当的I/O异常.如何修改此程序以具有该行为?

编辑:仔细检查hGetContents实现后,似乎不会忽略I/O异常,而是通过调用纯函数代码冒泡到触发评估的任何IO代码,然后有机会处理它.(我以前没有意识到纯函数代码会引发异常.)因此,这个问题是一个误解.

旁白:如果通过经验验证这种特殊行为,那将是最好的.不幸的是,很难模拟低级I/O错误.

error-handling haskell

3
推荐指数
1
解决办法
217
查看次数

如何读取(和解析)文件,然后附加到同一文件而不会出现异常?

我试图在Haskell中正确读取文件,但我似乎得到了这个错误.

***例外:neo.txt:openFile:资源忙(文件被锁定)这是我的代码.

import Data.Char
import Prelude
import Data.List
import Text.Printf
import Data.Tuple
import Data.Ord
import Control.Monad
import Control.Applicative((<*))

import Text.Parsec
    ( Parsec, ParseError, parse        -- Types and parser
    , between, noneOf, sepBy, many1    -- Combinators
    , char, spaces, digit, newline     -- Simple parsers
    )
Run Code Online (Sandbox Code Playgroud)

这些是电影领域.

type Title = String
type Director = String
type Year = Int
type UserRatings = (String,Int) 
type Film = (Title, Director, Year , [UserRatings])
type Period = (Year, Year)
type Database = [Film]
Run Code Online (Sandbox Code Playgroud)

这是所有类型的解析,以便从文件中正确读取

-- …
Run Code Online (Sandbox Code Playgroud)

haskell exception file locked

3
推荐指数
1
解决办法
591
查看次数

未能产生懒惰的溪流

我将尽可能简短地说明这个问题.

我希望在向命令行输入三个字符后完成此计算.但事实并非如此.我很好奇为什么会这样.

return . take 3 =<< sequence (repeat getChar)
Run Code Online (Sandbox Code Playgroud)

编辑:

我应该补充一点,我试图将选择与生成分开,因此希望产生一个我选择的无限字符流.

haskell

2
推荐指数
2
解决办法
242
查看次数

Haskell的hGetContents没有返回任何内容,即使我知道该文件包含文本

我有一小部分代码表现不像我预期的那样:

tempTest = do
    (_,tHand) <- openTempFile "." "tempTest.txt"
    hPutStr tHand "Test!"
    read <- hGetContents tHand
    putStrLn read
Run Code Online (Sandbox Code Playgroud)

它正确地写入文件,但当被要求将内容显示到屏幕时,它只显示一个新行(没有任何引号).鉴于这是多么简单,我假设我误解了getContents的工作原理.根据我的理解,它以块的形式读取文件,而不是一次读取所有文件; 这可以防止内存被正在读取的大量文件填满.为什么"阅读"没有从hGetContents接收任何内容?这里的任何帮助都将不胜感激.

haskell lazy-evaluation

1
推荐指数
1
解决办法
106
查看次数