将文件读入类型 - Haskell [英] Reading file into types - Haskell

查看:152
本文介绍了将文件读入类型 - Haskell的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  type Rating =(String,Int)

类型Film =(String,String,Int,[Rating])

我有一个文件数据:

 Blade Runner
Ridley Scott
1982
( Amy,5),(Bill),8),(Ian,7),(Kevin,9),(Emma,4),(Sam,7), ,4)

The Fly
David Cronenberg
1986
(Megan,4),(Fred,7), Chris,5),(Ian,0),(Amy,6)

我怎样才能通过文件存储所有的条目到像FilmDatabase = [电影]?

解决方案

Haskell提供了一个绘制您的方法的独特方式。以你知道的开始

 模块Main其中

类型Rating =(String,Int)
type Film =(String,String,Int,[Rating])

main :: IO()
main = do
films< - readFilmsratings.dat
print films

试图将这个程序加载到ghci中会产生

 films.hs:8:12:不在范围内:`readFilms'

它需要知道什么 readFilms 是,所以添加足够的代码来继续移动。

  readFilms = undefined 

这是一个函数,它应该执行与 Film 数据。重新加载此代码(使用:reload 命令或简称:r )以获得

 films.hs:9:3:
约束中含糊不清的类型变量`a0':使用`print'引起的
(显示a0)
...

print 的类型为

 Prelude>:t print 
print ::显示a => a - > IO()

换句话说, print 接受一个参数,非正式地知道如何显示自身(即将其内容转换为字符串)并创建一个I / O操作当执行时输出该字符串。它几乎或多或少是你期望 print 的工作方式:

 Prelude> print 3 
3
Prelude> printhi
hi

我们知道我们要 print > Film 文件中的数据,但是,虽然很好,但ghc不能理解我们的想法。但是在添加一个类型提示之后

  readFilms :: FilePath  - >电影
readFilms =未定义

我们收到一个新错误。 b

 films.hs:8:12:
无法与实际类型'(String,String,Int,[Rating]匹配预期类型'IO t0'
])'
预期类型:IO t0
实际类型:电影
在`readFilms'调用的返回类型中
在'do'表达式中:影片< - readFilmsratings.dat

该错误告诉您编译器对您的故事感到困惑。你说 readFilms 应该给它一个 Film ,但是你在 main ,计算机必须首先执行一些I / O然后然后返回 Film 数据。



在Haskell中,这是字符串(比如JamieB)和a在你提示你输入Stack Overflow用户名后,从键盘读取输入。



现在我们知道我们可以绘制 readFilms as

  readFilms :: FilePath  - > IO Film 
readFilms = undefined

以及代码编译! (但我们还不能运行它。)



要挖掘另一个图层,假设单个电影的名称是 ratings.dat ,然后在其他地方放置占位符来保持类型检查器的快乐。

  readFilms :: FilePath - > IO Film 
readFilms path = do
alldata< - readFile path
return(alldata,,0,[])

这个版本可以编译,甚至可以在ghci提示符处输入 main 来运行它。



dave4420的答案中提供了有关其他功能的重要提示。把上面的方法想象成一个拼图游戏,其中单个棋子是功能。为了您的程序正确,所有类型必须合在一起。你可以通过采取上述的小补充措施来使你的最终工作计划取得进展,如果你的草图中有错误,类型分析工具会告诉你。



物联网out:


  • 如何将整个输入块转换为单独的行

  • 你找出你的程序正在检查的行是标题,导演等?

  • 你如何转换文件中的年份(a String )添加到 Int 以配合您的定义电影

  • 你如何跳过空行或空行?
  • 电影数据

Right now I have two types:

type Rating = (String, Int)

type Film = (String, String, Int, [Rating])

I have a file that has this data in it:

"Blade Runner"
"Ridley Scott"
1982
("Amy",5), ("Bill",8), ("Ian",7), ("Kevin",9), ("Emma",4), ("Sam",7), ("Megan",4)

"The Fly"
"David Cronenberg"
1986
("Megan",4), ("Fred",7), ("Chris",5), ("Ian",0), ("Amy",6)

How can I look through then file storing all of the entries into something like FilmDatabase = [Film] ?

解决方案

Haskell provides a unique way of sketching out your approach. Begin with what you know

module Main where

type Rating = (String, Int)
type Film = (String, String, Int, [Rating])

main :: IO ()
main = do
  films <- readFilms "ratings.dat"
  print films

Attempting to load this program into ghci will produce

films.hs:8:12: Not in scope: `readFilms'

It needs to know what readFilms is, so add just enough code to keep moving.

readFilms = undefined

It is a function that should do something related to Film data. Reload this code (with the :reload command or :r for short) to get

films.hs:9:3:
    Ambiguous type variable `a0' in the constraint:
      (Show a0) arising from the use of `print'
    ...

The type of print is

Prelude> :t print
print :: Show a => a -> IO ()

In other words, print takes a single argument that, informally, knows how to show itself (that is, convert its contents to a string) and creates an I/O action that when executed outputs that string. It’s more-or-less how you expect print to work:

Prelude> print 3
3
Prelude> print "hi"
"hi"

We know that we want to print the Film data from the file, but, although good, ghc can’t read our minds. But after adding a type hint

readFilms :: FilePath -> Film
readFilms = undefined

we get a new error.

films.hs:8:12:
    Couldn't match expected type `IO t0'
                with actual type `(String, String, Int, [Rating])'
    Expected type: IO t0
      Actual type: Film
    In the return type of a call of `readFilms'
    In a stmt of a 'do' expression: films <- readFilms "ratings.dat"

The error tells you that the compiler is confused about your story. You said readFilms should give it back a Film, but the way you called it in main, the computer should have to first perform some I/O and then give back Film data.

In Haskell, this is the difference between a pure string, say "JamieB", and a side effect, say reading your input from the keyboard after prompting you to input your Stack Overflow username.

So now we know we can sketch readFilms as

readFilms :: FilePath -> IO Film
readFilms = undefined

and the code compiles! (But we can’t yet run it.)

To dig down another layer, pretend that the name of a single movie is the only data in ratings.dat and put placeholders everywhere else to keep the typechecker happy.

readFilms :: FilePath -> IO Film
readFilms path = do
  alldata <- readFile path
  return (alldata, "", 0, [])

This version compiles, and you can even run it by entering main at the ghci prompt.

In dave4420’s answer are great hints about other functions to use. Think of the method above as putting together a jigsaw puzzle where the individual pieces are functions. For your program to be correct, all the types must fit together. You can make progress toward your final working program by taking little babysteps as above, and the typechecker will let you know if you have a mistake in your sketch.

Things to figure out:

  • How do you convert the whole blob of input to individual lines?
  • How do you figure out whether the line your program is examining is a title, a director, and so on?
  • How do you convert the year in your file (a String) to an Int to cooperate with your definition of Film?
  • How do you skip blank or empty lines?
  • How do you make readFilms accumulate and return a list of Film data?

这篇关于将文件读入类型 - Haskell的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆