質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.02%
Haskell

Haskellは高い機能性をもった関数型プログラミング言語で、他の手続き型プログラミング言語では難しいとされている関数でも容易に行うことができます。強い静的型付け、遅延評価などに対応しています。

Q&A

受付中

haskellでテキストファイルを読み込んで1行ずつ配列に入れたい

退会済みユーザー

退会済みユーザー

総合スコア0

Haskell

Haskellは高い機能性をもった関数型プログラミング言語で、他の手続き型プログラミング言語では難しいとされている関数でも容易に行うことができます。強い静的型付け、遅延評価などに対応しています。

1回答

0グッド

0クリップ

645閲覧

投稿2021/07/04 09:51

https://www.nslabs.jp/haskell-fileio.rhtml
上記のサイトの「テキストファイルを1行ずつ表示する関数」を「1行ずつ読み込んで多重配列にいれる」という関数に改造したいと考えて下記のコードを書きました
しかしsplitEvery 1 strで
textsample.hs:35:9: error: parse error on input ‘splitEvery’
|
35 | splitEvery 1 str[]--1文字ずつ分割
というエラーが吐かれます
どうしたら動きますか。教えてください

haskell

1text_get_array :: Handle->[a] 2text_get_array fp 3 |hIsEOF fp ==true =[] 4 |otherwise= 5 let str[] = DTI.hGetLine fp --1行読み込み 6 splitEvery 1 str--1文字ずつ分割 7 str ++ get_and_print fp

"qwertuiop"
"asdfgjkl"
"zxcvbnm"
とサンプルでは出力されるので
[[q,w,e,r,t,u,i,o,p],[a,s,d,f,g,j,k,l],[z,x,c,v,b,n,m]]
という配列を取得したい

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答1

2

回答を2つの部分に分けます。1つめは「1行ずつ読み込んで多重配列にいれる」を解決する部分、2つめは掲載のコードの問題点を指摘する部分です。


まず1つめの「1行ずつ読み込んで多重配列にいれる」を実装すると下記のようになります(Wandbox で実行)。

haskell

1main :: IO () 2main = do 3 c <- getContents 4 let ls = lines c 5 print ls

解説です。

初めに Haskell では配列はほとんど使われません(少なくとも初心者のうちは)。代わりに連結リストを使います。
標準入力を [[Char] の型の値で得るのが getContents です(ドキュメント)。
[Char] は標準で String という別名がついています(ドキュメント)。
getContents の型は IO [String] つまり IO [[Char]] です。
IO a という型の値から a という型の値を取り出すには do 構文の <- という構文を使います。
ですので上記コードでは c[String] という型になります。
次に lines 関数を使います。
これは String -> [String] という型で、引数の文字列を CR や LF で分割し、文字列のリストとして返します(ドキュメント)。
こうすると ls の型は [String] つまり [[Char]] となります。
これを print で出力します。


次に掲載コードの問題点です。

haskell

1text_get_array :: Handle->[a] -- (1) 2text_get_array fp 3 |hIsEOF fp ==true =[] -- (2) 4 |otherwise= 5 let str[] = DTI.hGetLine fp --1行読み込み -- (3) 6 splitEvery 1 str--1文字ずつ分割 -- (4) 7 str ++ get_and_print fp -- (5)
  1. この関数は内部に IO の操作をするため返り値の型は必ず IO a という形になります。
  2. hIsEOFHandle -> IO Bool という型の関数なので、Bool の値を得るためには do<- の構文を使う必要があります(ドキュメント)。
  3. hIsEOF と同じく Data.Text.IO.hGetLineHandle -> IO Text という型なので do<- の構文を使います。また、変数名の後に [] を書く構文はありません。
  4. Haskell では変数を再束縛できないため操作した結果を取得するためには返り値が必要です(純粋な関数の場合)。ここでは返り値がないため操作の結果を捨てていることになります。
  5. ここも同様に get_and_printIO a のような型の値を返すので do<- が必要です。

str[] のような書き方を見るに C 系の文法の推測でコードを書いていらっしゃるようですが、Haskell はそのような系統とは文法が異なります。推測ではなかなか書けませんので一度 C 系は忘れてしまうのが得策です。

投稿2021/07/04 14:28

kakkun61

総合スコア285

nobkz, igrep👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

退会済みユーザー

退会済みユーザー

2021/07/05 00:49

ありがとうございます

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.02%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Haskell

Haskellは高い機能性をもった関数型プログラミング言語で、他の手続き型プログラミング言語では難しいとされている関数でも容易に行うことができます。強い静的型付け、遅延評価などに対応しています。