3
checkstring :: [String] -> Int -> [String]
checkstring p n = do    z <- doesFileExist (p !! n)
    if z
    then p
    else error $ "'" ++ (p !! n) ++ "' file path does not exist"

「n」を調べて文字列内の要素をチェックし(したがって、n = 2 の場合、リストの 2 番目の文字列かどうかをチェックします)、それが存在するかどうかを確認します。存在する場合は元の文字列リストを返し、存在しない場合はエラーになります.なぜこれを行うのですか? :

Couldn't match expected type `[t0]' with actual type `IO Bool'
    In the return type of a call of `doesFileExist'
    In a stmt of a 'do' expression: z <- doesFileExist (p !! n)
4

3 に答える 3

6

の型はdoesFileExistですString -> IO Bool。プログラムがファイルが存在するかどうかを知りたい場合は、IO アクションであるファイル システムとやり取りする必要があります。関数でそれを行う場合checkStringは、ある種の IO ベースの型も必要です。たとえば、試したことはありませんが、次のようなものがうまくいくと思います。

checkstring :: [String] -> Int -> IO [String]
checkstring p n = do    z <- doesFileExist (p !! n)
    if z
    then return p
    else error $ "'" ++ (p !! n) ++ "' file path does not exist"
于 2011-08-15T04:41:45.000 に答える
2

MatrixFrog が回答で言及した内容に追加します。関数の署名を見ると、つまり[String] -> Int -> [String]、この関数が純粋な関数であり、副作用がないことを示しています。使用している関数本体 のように、IO の存在が不純であることを示すdoesFileExist署名があります。String -> IO Boolつまり、何らかの IO が含まれます。Haskell では、不純な関数と純粋な関数の間に厳密な分離があり、実際のところ、関数が不純な他の関数を呼び出す場合、関数も不純です。したがって、あなたの場合、関数checkStringは不純である必要があり、それは return にすることで実行できますIO [String]。これは、MatrixFrog が彼の回答で言及したことです。


checkString :: String -> IO (Maybe String)別の注意として、関数を次のようにすることをお勧めします。エラーを検出するために Maybe を使用できます。これは単なる提案ですが、関数の使用方法にも依存します。

于 2011-08-15T10:16:49.603 に答える
0

問題は、型シグネチャがdoブロックに他のモナドであると想定させることだと思います。たとえば、リストモナドで作業しているとします。次に、書くことができます

myFcn :: [String] -> Int -> [String]
myFcn p n = do
    return (p !! n)

リスト モナドの場合、 はreturn単純にシングルトン リストを返すため、次のような動作が得られます。

> myFcn ["a", "bc", "d"] 1
["bc"]

(私の個人的な意見では、GHC に型エラーを引き起こす可能性のあるよくある間違いを出力するオプションがあれば非常に役立つだろうということです。探し出す)。

于 2011-08-15T08:30:43.840 に答える