在几个教程之后,现在在Haskell中创建我的第一个“真实”代码。
我有一个系统,我将使用评分函数来表示我希望表示为Int
的条目对,因此该函数基本上只是一个[[Int]]
,否则性能要求。此函数的构建取决于指定为程序命令行参数的文本文件中的数字。
我的程序的所有部分都使用指定的硬编码[[Int]]
(oops!)正常工作,然后我来到了必须在Haskell中读取IO的阶段,然后我意识到我的错误(?):我已经做了一些事情,我必须从输入文件中构造[[Int]]
并将其作为额外参数传递给需要使用对的分数的函数。现在在我看来,而不是
ranking :: (Int, Int) -> Int
我必须这样做
rankingBasedOnInput :: SomeType -> (Int, Int) -> Int
其中SomeType
是我的函数签名右侧的一部分,用于处理输入文件:IO SomeType
。
我希望有人可以告诉我和我的程序性思维做错了什么,并提示创建一个更好的解决方案,因为我仍然是新的思维方式。
答案 0 :(得分:3)
您可能不想知道主代码中的[[Int]],而是在评分函数中对其进行抽象。您可以传递排名函数((Int,Int) - > Int),而不是在调用者中明确使用“rankingBasedOnInput”函数。
someFunction :: a -> b
someFunction input = ...
where f x = rankingBasedOnInput input x
与
一起使用someFunction a
成为:
someFunction :: ((Int,Int) -> Int) -> a -> b
someFunction ranking x
用于:
someFunction ranking a
where ranking = rankingBasedOnInput input
不是传递输入参数,而是传递评分函数。
您仍然可以显式传递参数。但是,您可以使用部分功能应用程序尽可能地避免它。
答案 1 :(得分:3)
所以你的问题是排名函数依赖于文本文件中可能发生的变化数据?
如果排名是纯函数,则是,计算排名所需的所有数据都需要在函数的输入中,因此您的类型签名需要类似于:
ranking :: SomeType -> (Int,Int) -> Int
这很好用,唯一的问题是你必须通过所有使用它的函数显式地处理状态。
另一个显而易见的选择,如果你在很多不同的地方出现状态(例如排名),就是使用State或Reader Monad作为顶级功能。在我下面的例子中,我使用State monad,因为我不知道你是否需要在首次阅读之后修改你的共享状态。
这些有效地隐藏了这样一个事实,即状态正在贯穿所有内容,并且会让你写下类似的内容:
-- import state monad
import Control.Monad.State
-- create type synonym to reduce type signature length
type MyMonad a = State SomeType a
-- dependence of ranking on state is via MyMonad rather than explicit input argument
ranking :: (Int,Int) -> MyMonad Int
ranking = do
rankingData <- get
calculate rank somehow with rankingData
return rank
-- define a function that does all the work
doCalculationsWithRanks :: unknown inputs -> MyMonad (unknown return type)
doCalculationsWithRanks = undefined
-- run the program and get the results
main = do
rankingData <- readRankingsFromFile
let myResults = evalState (doCalculationsWithRanks ...) rankingData
do something with the myResults
如果你需要IO和状态,你可以创建一个monad转换器来创建一个monad,让你可以访问IO,但也为你带来状态。
另外,正如ysdx所说,你可以部分应用排名来摆脱额外的争论:
ranking' = ranking rankingData
这意味着您需要为每个需要计算排名的函数添加一个函数参数,因此在这种情况下,您仍然需要为某些函数添加额外的参数。