ハスケルは、あなたのアプローチをスケッチするユニークな方法を提供します。あなたはGHCiのにこのプログラムをロードしようとすると、
module Main where
type Rating = (String, Int)
type Film = (String, String, Int, [Rating])
main :: IO()
main = do
films <- readFilms "ratings.dat"
print films
知っていることで始まると、それはreadFilms
が何であるかを知っているので、移動保つために必要なだけのコードを追加する必要が
films.hs:8:12: Not in scope: `readFilms'
を生成します。
readFilms = undefined
これは、Film
データに関するものです。 print
は、非公式に、どのように知っている単一の引数を取り、print
の種類は、言い換えれば
Prelude> :t print
print :: Show a => a -> IO()
ある
films.hs:9:3:
Ambiguous type variable `a0' in the constraint:
(Show a0) arising from the use of `print'
...
を取得する(:reload
コマンドまたは略して:r
で)このコードをリロードその内容を文字列に変換し、実行時にその文字列を出力するI/Oアクションを作成します。それ’ S多かれ少なかれあなたはprint
が動作することを期待する方法:
Prelude> print 3
3
Prelude> print "hi"
"hi"
私たちは、ファイルからFilm
データをprint
したいことを知っている、しかし、良いものの、GHCはtは私たちの心を読む’ことができます。しかし、タイプヒントを追加した後
readFilms :: FilePath -> Film
readFilms = undefined
新しいエラーが発生します。
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"
このエラーは、コンパイラがあなたの話について混乱していることを示しています。あなたはreadFilms
がFilm
を返すべきだと言いましたが、main
でそれを呼び出す方法では、コンピュータは最初にいくつかのI/Oを実行し、を実行してからデータを返す必要があります。Film
Haskellで
、これは純粋文字列、"JamieB"
を言うと、副作用との間の差である、入力にあなたのスタックオーバーフローのユーザー名をあなたに要求した後、キーボードからの入力内容を読ん言います。
だから今、私たちはreadFilms
readFilms :: FilePath -> IO Film
readFilms = undefined
としてをスケッチし、コードのコンパイルすることができます知っています!
別のレイヤーを掘り下げるには、1つのムービーの名前がratings.dat
の唯一のデータであり、タイプチェッカーを幸せにするために他の場所に置くことをお勧めします。
readFilms :: FilePath -> IO Film
readFilms path = do
alldata <- readFile path
return (alldata, "", 0, [])
このバージョンでは、コンパイルし、あなたもGHCiのプロンプトでmain
を入力することによって、それを実行することができます。
dave4420’s answerは、使用する他の機能についての大きなヒントです。上記の方法は、個々の要素が機能するジグソーパズルを組み立てることと考えてください。あなたのプログラムが正しいようにするには、すべてのタイプが一緒に適合しなければなりません。あなたは上記のようにほとんどbabystepsを取ることによってあなたの最終作業プログラムに向かって進歩することができ、あなたがあなたのスケッチに間違いがあるかどうかをタイプチェッカーが知らせます。把握する
もの:
- あなたは個々の行への入力の全体のブロブを変換する方法を教えてください。
- あなたのプログラムが調査している行がタイトルかディレクターかなどをどのように把握していますか?
- ファイルの年(
String
)をInt
に変換すると、Film
の定義にどのように協力しますか?
- 空白行または空白行をどのようにスキップしますか?
readFilms
をどのように蓄積し、Film
のデータのリストを返しますか?
のような単純なもの: \t \t \t \t名< - getlineの \t \t \t \t内容< - readFileの名 :displayFile :: IO() displayFileは= \t \t \t \t putStrLnは、 "ファイル名を入力します" ん\t \t \t putStrLnの内容 – JamieB
どのビットで問題がありますか? – dave4420
私はどのように行をフィルタリングし、右のタイプに追加するのか分かりません。各エントリの最初の行は文字列でなければならず、映画(タイトルなど)のタイトルに追加する必要がありますC#ではシンプルですが、私はそれをHaskellで信じられないほど難しくしています。 – JamieB