4

countInFile0とcountInFile2にコンパイラエラーがないのに、countInFile1とcountInFile3にコンパイラエラーがあるのはなぜですか。4つすべてが同じものです。

count :: String -> String -> Int
count w = length . filter (==w) . words

present :: String -> String -> IO String
present w = return . show . count w

-- VALID: pointed readFile, regular present
countInFile0 :: String -> FilePath -> IO ()
countInFile0 w f = putStrLn =<< present w =<< readFile f

-- INVALID: pointless readFile, regular present
countInFile1 :: String -> FilePath -> IO ()
countInFile1 w = putStrLn =<< present w =<< readFile

-- VALID: pointed readFile, inline present
countInFile2 :: String -> FilePath -> IO ()
countInFile2 w f = putStrLn =<< (return . show . count w) =<< readFile f

-- INVALID: pointless readFile, inline present
countInFile3 :: String -> FilePath -> IO ()
countInFile3 w = putStrLn =<< (return . show . count w) =<< readFile

main = do
  countInFile0 "bulldogs" "bulldogs.txt"
  countInFile1 "bulldogs" "bulldogs.txt"
  countInFile2 "bulldogs" "bulldogs.txt"
  countInFile3 "bulldogs" "bulldogs.txt"

また、countInFile3には、countInFile1にはないこの追加のエラーがあるのはなぜですか。

example_one.hs:21:27:
    No instance for (Monad ((->) FilePath))
      arising from a use of `=<<'
    Possible fix:
      add an instance declaration for (Monad ((->) FilePath))
    In the expression:
        putStrLn =<< (return . show . count w) =<< readFile
    In an equation for `countInFile3':
        countInFile3 w
          = putStrLn =<< (return . show . count w) =<< readFile
4

2 に答える 2

9

との両方countInFile1を使用countInFile3して、形式の3つのものを構成a -> IO bしているので、いわゆるクライスリ構成、<=<fromを考えていControl.Monadます。試す

 countInFile1 w = putStrLn <=< present w <=< readFile
 countInFile3 w = putStrLn <=< return . show . count w <=< readFile

または、他の場所と同じようcountInFile3 w file = ... =<< readFile fileに、を書くこともできます。readFile file(パラメータを使用して)は。であるため、任意の。によって、または任意の。IO Stringに渡すことができます。しかし、それはあなたが意図したものほどしゃれたものではありません。 それ自体がそうなので、あなたの場合は、で終わるなどで、などを作るために任意のもので'dすることができます>>==<<String -> IO breadFileFilePath -> IO String>=>String -> IO bFilePath -> IO bb -> IO cFilePath -> IO ()

2番目のエラーは、ghcが読み込もうとしたことによるものです。これを行うには、モナドmに対してmbである=<< readFile必要があるため、解決します(これは、実際には意味がありますが、最初のエラーの取得が遅れるだけです)。readFileMonad ((->) FilePath)Control.Monad.Instances

fileこれらにパラメータを追加すると、次のようになります。

 countInFile1 w file = (putStrLn <=< present w <=< readFile) file 

そして、実際にはそのように解釈しているときに、このように構文解析している可能性がありますcountInFile2countInFile0=<<<=<

 countInFile0 w file = putStrLn =<< present w =<< (readFile file)

違いは

 f n = (even . (+1) . (*3)) n

または同等に

 f   = even . (+1) . (3*)

一方で

 f n = even $ (+1) $ 3 * n  -- cp. your 0 and 2

nここで両側から削除すると

 f   = even $ (+1) $ (3*)  -- cp. your 1 and 3

見たものと同様のタイプエラーが発生します。

 No instance for (Integral (a0 -> a0)) arising from a use of `even'

使用する場所に$はパラメータが必要nです-使用する場所>>=またはパラメータ=<<が必要な場所と同じですfile。を使用.すると、と同様に<=<、使用しません。

于 2012-09-18T04:05:26.217 に答える
8

=<<関数適用は、中置演算子よりも優先されます。

したがってf =<< g a、と同等でf =<< (g a)あり、ではありません(f =<< g) a

于 2012-09-18T04:03:27.690 に答える