Reputation: 1491
Ok, so let's say I have a function which takes a String and returns a certain value of that string specified by a text file. A text file will look like this.
hello - 2
bye - 3
so the function would return 2 given "hello" and 3 given "bye". Now, the function is of type Weight (I can't change it as this is the part of the framework):
type Weight = String -> Int
How do I implement such function given that it HAS TO be of the type Weight. The problem is that I don't know how to make weight aware of what value to return given a certain string. I can't hardcode the values because they will be different in different textfiles. And I can't have readFile inside the function or anything like that, right? Are there any other options?
Upvotes: 0
Views: 116
Reputation: 13677
You cannot have assignWeight
globally, but you can have it locally with the genuine non-IO type you wanted. I think the approach below is a common pattern used to separate monadic code from non-monadic.
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
Here assignWeight
is of correct type. You can pass it around: look how I passed it to non-monadic process
function. You cannot have assignWeight
defined at top level without violating purity, as other commenters pointed out, but to have it locally and pass around is a commonly used approach.
Here is a more modular approach:
getAssignWeight :: IO Weight
getAssignWeight = do
content <- parseFile
let assignWeight x = fromJust $ lookup x content
return assignWeight
main = do
assignWeight <- getAssignWeight
print $ process assignWeight
Upvotes: 0
Reputation: 53901
You have two choices,
assignWeight :: String -> IO Int
assignWeight = do
file <- readFile whatever
-- parse file and extract a function assigning strings to their weights
return $ parseFile file
Or,
assignWeight :: String -> Weight
assignWeight file = parseFileAndExtractWeights file
and then read the file in main
and use currying. So there's not toplevel function, but we still get our function later by partially applying assignWeight
to the contents of the file
main = do
weights <- assignWeight `fmap` readFile whatever
-- use weights
But you can't perform IO in a computation of type Weight
, so you'll either have to perform it elsewhere and pass the type to it or just change the type. No other way about it.
Upvotes: 3