0

では、文字列を受け取り、テキスト ファイルで指定された文字列の特定の値を返す関数があるとします。テキストファイルは次のようになります。

こんにちは - 2
さようなら - 3

そのため、この関数は「こんにちは」の場合は 2 を返し、「さようなら」の場合は 3 を返します。現在、関数のタイプは Weight です (これはフレームワークの一部であるため、変更できません)。

type Weight = String -> Int

Weight 型である必要がある場合、そのような関数をどのように実装しますか。問題は、特定の文字列が返される値を重みに認識させる方法がわからないことです。テキストファイルによって値が異なるため、値をハードコードすることはできません。そして、関数内に readFile などを含めることはできませんよね?他のオプションはありますか?

4

2 に答える 2

3

2 つの選択肢があります。

assignWeight :: String -> IO Int
assignWeight = do
  file <- readFile whatever

  -- parse file and extract a function assigning strings to their weights
  return $ parseFile file

または、

assignWeight :: String -> Weight
assignWeight file = parseFileAndExtractWeights file

次に、ファイルを読み込んでmainカリー化を使用します。したがって、トップレベルの関数はありませんassignWeightが、ファイルの内容に部分的に適用することで、後で関数を取得します

main = do
  weights <- assignWeight `fmap` readFile whatever
  -- use weights

ただし、 type の計算で IO を実行することはできないためWeight、別の場所で実行して型を渡すか、単に型を変更する必要があります。他に方法はありません。

于 2013-10-26T13:07:09.757 に答える
0

グローバルに持つことはできませんがassignWeight、必要な本物の非 IO タイプでローカルに持つことができます。以下のアプローチは、モナドコードを非モナドコードから分離するために使用される一般的なパターンだと思います。

import Data.Maybe
import Control.Applicative

parseFile :: IO [(String, Int)]
parseFile = read <$> readFile "Parse.txt"

main = do
        content <- parseFile
        let assignWeight x = fromJust $ lookup x content
        print $ process assignWeight

type Weight = String -> Int

process :: Weight -> Int
process x = 0

こちらassignWeightが正しいタイプです。あなたはそれを渡すことができます:私がそれを非モナドprocess関数にどのように渡したかを見てください。assignWeight他のコメンターが指摘したように、純粋性に違反することなくトップレベルで定義することはできませんが、それをローカルに保持して渡すことは、一般的に使用されるアプローチです。

これは、よりモジュール化されたアプローチです。

getAssignWeight :: IO Weight
getAssignWeight = do
        content <- parseFile
        let assignWeight x = fromJust $ lookup x content
        return assignWeight

main = do
        assignWeight <- getAssignWeight
        print $ process assignWeight
于 2013-10-27T10:31:41.593 に答える