Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何对调用使用该状态的其他函数的函数隐藏状态_Haskell_State Monad - Fatal编程技术网

Haskell 如何对调用使用该状态的其他函数的函数隐藏状态

Haskell 如何对调用使用该状态的其他函数的函数隐藏状态,haskell,state-monad,Haskell,State Monad,我希望在Haskell程序中有一些更高级的函数调用其他函数,这些函数最终调用使用某种状态或配置的函数,而不必在所有这些函数调用中传递状态。我知道这是state monad(或者可能是Reader monad?)的经典用法 (我也不确定是否应该使用StateT(如下面的示例所示)来启用do IO,或者是否应该以某种方式单独输出结果。) 在这个阶段,我对这里所有的教程、博客帖子和类似的问题感到非常困惑,无法找到解决方案。还是我误解了隐藏的东西 下面是一个小例子: import Control.Mon

我希望在Haskell程序中有一些更高级的函数调用其他函数,这些函数最终调用使用某种状态或配置的函数,而不必在所有这些函数调用中传递状态。我知道这是state monad(或者可能是Reader monad?)的经典用法

(我也不确定是否应该使用StateT(如下面的示例所示)来启用do IO,或者是否应该以某种方式单独输出结果。)

在这个阶段,我对这里所有的教程、博客帖子和类似的问题感到非常困惑,无法找到解决方案。还是我误解了隐藏的东西

下面是一个小例子:

import Control.Monad.State

-- Here's a simple configuration type:
data Config = MkConfig {
      name :: String
    , num  :: Int
    } deriving Show

-- Here's a couple of configurations.
-- (They're hard coded and pre-defined.)
c1 = MkConfig "low" 7
c2 = MkConfig "high" 10

-- Here's a lower level function that explicitly uses the config.
-- (The String is ignored here for simplicity, but it could be used.)
fun :: Config -> Int -> Int
fun (MkConfig _ i) j = i*j

-- testA and GoA work fine as expected.
-- fun uses the different configs c1,c2 in the right way.
testA = do
    a <- get
    lift (print (fun a 2))
    put c2
    a <- get
    lift (print (fun a 4))

goA = evalStateT testA c1
-- (c1 could be put at the start of testA instead.)

-- But what I really want is to use fun2 that calls fun, 
-- and not explicitly need state.
-- But this function definition does not compile:
fun2 :: Int -> Int
fun2 j = 3 * fun cf j  
-- fun needs a config arg cf, but where from?

-- I would like a similar way of using fun2 as in testB and goB here.
testB = do
    a <- get
    lift (print (fun2 3))  -- but fun2 doesn't take the state in a 
    put c2
    a <- get
    lift (print (fun2 42))  -- but fun2 doesn't take the state in a 

goB = evalStateT testB c1 
import Control.Monad.State
--下面是一个简单的配置类型:
数据配置=MkConfig{
名称::字符串
,num::Int
}衍生节目
--这里有几个配置。
--(它们是硬编码和预定义的。)
c1=MkConfig“低”7
c2=MkConfig“高”10
--下面是一个显式使用配置的低级函数。
--(为简单起见,此处忽略该字符串,但可以使用它。)
乐趣::配置->整型->整型
fun(MkConfig i)j=i*j
--testA和GoA工作正常。
--fun以正确的方式使用不同的配置c1、c2。
testA=do
当然,您不能在类型签名中完全“隐藏配置”:普通的旧函数
Int->Int
必须是引用透明的,因此它也不能依赖或接受某些
Config

您可能想做的是:

fun2 :: Int -> State Config Int    -- An `Int -> Int` that depends on `Config` state.
                                   -- Compare to how `Int -> IO Int` is like an
                                   -- `Int -> Int` function that depends on IO.
fun2 j = do
  c1 <- get
  return (3 * fun c1 j)

另见:

然后你可以写一些像

let result = evalState (fun2 42) c    -- An Int.
testB :: StateT Config IO ()
testB = do
    -- Fancy:
    result <- hoistState (fun2 42)

    -- Equivalent:
    c <- get
    let result' = evalState (fun2 42) c

    lift (print (result, result'))
testB::StateT配置IO()
testB=do
--幻想:
结果
testB :: StateT Config IO ()
testB = do
    -- Fancy:
    result <- hoistState (fun2 42)

    -- Equivalent:
    c <- get
    let result' = evalState (fun2 42) c

    lift (print (result, result'))