0

好的,假设我有一个函数,它接受一个字符串并返回由文本文件指定的该字符串的某个值。一个文本文件将如下所示。

你好 - 2
再见 - 3

因此该函数将返回 2 给定“hello”和 3 给定“bye”。现在,该函数是 Weight 类型(我无法更改它,因为这是框架的一部分):

type Weight = String -> Int

鉴于它必须是权重类型,我该如何实现这样的功能。问题是我不知道如何让权重知道给定某个字符串要返回什么值。我无法对这些值进行硬编码,因为它们在不同的文本文件中会有所不同。而且我不能在函数内有 readFile 或类似的东西,对吧?还有其他选择吗?

4

2 回答 2

3

你有两个选择,

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 回答