从 Haskell 中的 2 个州获取数据
Get data from 2 states in Haskell
我正在 Haskell 中编写一个小型解释器,它使用 StateT-monad(结合 IO)和 EitherT monad。现在我想将一个整数函数应用于由 interpArithmic 函数解释的值。但问题是 interpArithmic 本身也有 EitherT InterpError (StateT Environment IO ())
签名。我如何提取由 interpArithmic 函数解释的值,在我的 bAritHelper 函数中使用它,将它们加在一起(例如)并 return 有新值?
bArithHelper :: Arithmic -> Arithmic -> (Integer -> Integer -> Integer) -> EitherT InterpError (StateT Environment IO Value)
bArithHelper a b func =
-- Body of this function is completely broken, don't know how to fix this.
do
st1 <- interpArithmic a
st2 <- interpArithmic b
return $ do
env1 <- get st1
env2 <- get st2
return Num
liftM $
-- This function interpretes an arithmic expression and returns it's result.
-- An error message (int the form of Error) is returned in case something goes wrong.
interpArithmic :: Arithmic -> Either InterpError (StateT Environment IO Value)
interpArithmic (ConstInteger a) = return (Num a)
interpArithmic (BinaryArithmicExpression Add a b) = bArithHelper a b (\x -> \y -> x + y)
或者是否有其他方法来处理错误并将 StateT monad 与 IO 结合使用?
PS:我想保留 EitherT 作为外部 monad 转换器,因为这样我就不必在 do-block 中使用某种大小写。
您的代码中缺少相当多的上下文,因此我已尽力将其拼凑成可以自行编译的代码。您的类型签名也有延伸有点过远的括号。大概 Either
也意味着 EitherT
。
我仍然对您到底想要什么感到有点困惑,因为您似乎快到了,但是以下内容是否与您正在寻找的内容类似(这会按您的预期进行编译)?也许您认为 st1 <- interpArithmic
只是 "unwrapping one layer",因此返回 StateT ...
而实际上 st1
是 Value
?
import Control.Monad.Trans.Except
import Control.Monad.Trans.State
type EitherT = ExceptT
data Arithmic = ConstInteger Integer | BinaryArithmicExpression Exp Arithmic Arithmic
data Value = Num Integer
data Exp = Add
type InterpError = String
type Environment = String
getVal :: Value -> Integer
getVal (Num x) = x
bArithHelper :: Arithmic -> Arithmic -> (Integer -> Integer -> Integer) -> EitherT InterpError (StateT Environment IO) Value
bArithHelper a b func =
do
st1 <- interpArithmic a
st2 <- interpArithmic b
return $ Num (func (getVal st1) (getVal st2))
interpArithmic :: Arithmic -> EitherT InterpError (StateT Environment IO) Value
interpArithmic (ConstInteger a) = return (Num a)
interpArithmic (BinaryArithmicExpression Add a b) = bArithHelper a b (\x -> \y -> x + y)
你的问题缺少一些数据类型定义,所以我从上下文中推断出我认为你的意思。这是我得到的:
module Main where
import Control.Monad.Trans.Either
import Control.Monad.Trans.State
data InterpError = InterpError () deriving (Show)
data Environment = Environment () deriving (Show)
data Op = Add deriving (Show)
data Value = Num Integer deriving (Show)
data Arithmic = ConstInteger Integer
| BinaryArithmicExpression Op Arithmic Arithmic
deriving (Show)
bArithHelper :: Arithmic -> Arithmic -> (Integer -> Integer -> Integer) -> EitherT InterpError (StateT Environment IO) Value
bArithHelper a b func = do
Num st1 <- interpArithmic a
Num st2 <- interpArithmic b
return $ Num $ func st1 st2
-- This function interpretes an arithmic expression and returns it's result.
-- An error message (int the form of Error) is returned in case something goes wrong.
interpArithmic :: Arithmic -> EitherT InterpError (StateT Environment IO) Value
interpArithmic (ConstInteger a) = return (Num a)
interpArithmic (BinaryArithmicExpression Add a b) = bArithHelper a b (\x -> \y -> x + y)
main :: IO ()
main = do
res <- runStateT (runEitherT $ interpArithmic (BinaryArithmicExpression Add (ConstInteger 2) (ConstInteger 3))) $ Environment ()
print res
我正在 Haskell 中编写一个小型解释器,它使用 StateT-monad(结合 IO)和 EitherT monad。现在我想将一个整数函数应用于由 interpArithmic 函数解释的值。但问题是 interpArithmic 本身也有 EitherT InterpError (StateT Environment IO ())
签名。我如何提取由 interpArithmic 函数解释的值,在我的 bAritHelper 函数中使用它,将它们加在一起(例如)并 return 有新值?
bArithHelper :: Arithmic -> Arithmic -> (Integer -> Integer -> Integer) -> EitherT InterpError (StateT Environment IO Value)
bArithHelper a b func =
-- Body of this function is completely broken, don't know how to fix this.
do
st1 <- interpArithmic a
st2 <- interpArithmic b
return $ do
env1 <- get st1
env2 <- get st2
return Num
liftM $
-- This function interpretes an arithmic expression and returns it's result.
-- An error message (int the form of Error) is returned in case something goes wrong.
interpArithmic :: Arithmic -> Either InterpError (StateT Environment IO Value)
interpArithmic (ConstInteger a) = return (Num a)
interpArithmic (BinaryArithmicExpression Add a b) = bArithHelper a b (\x -> \y -> x + y)
或者是否有其他方法来处理错误并将 StateT monad 与 IO 结合使用?
PS:我想保留 EitherT 作为外部 monad 转换器,因为这样我就不必在 do-block 中使用某种大小写。
您的代码中缺少相当多的上下文,因此我已尽力将其拼凑成可以自行编译的代码。您的类型签名也有延伸有点过远的括号。大概 Either
也意味着 EitherT
。
我仍然对您到底想要什么感到有点困惑,因为您似乎快到了,但是以下内容是否与您正在寻找的内容类似(这会按您的预期进行编译)?也许您认为 st1 <- interpArithmic
只是 "unwrapping one layer",因此返回 StateT ...
而实际上 st1
是 Value
?
import Control.Monad.Trans.Except
import Control.Monad.Trans.State
type EitherT = ExceptT
data Arithmic = ConstInteger Integer | BinaryArithmicExpression Exp Arithmic Arithmic
data Value = Num Integer
data Exp = Add
type InterpError = String
type Environment = String
getVal :: Value -> Integer
getVal (Num x) = x
bArithHelper :: Arithmic -> Arithmic -> (Integer -> Integer -> Integer) -> EitherT InterpError (StateT Environment IO) Value
bArithHelper a b func =
do
st1 <- interpArithmic a
st2 <- interpArithmic b
return $ Num (func (getVal st1) (getVal st2))
interpArithmic :: Arithmic -> EitherT InterpError (StateT Environment IO) Value
interpArithmic (ConstInteger a) = return (Num a)
interpArithmic (BinaryArithmicExpression Add a b) = bArithHelper a b (\x -> \y -> x + y)
你的问题缺少一些数据类型定义,所以我从上下文中推断出我认为你的意思。这是我得到的:
module Main where
import Control.Monad.Trans.Either
import Control.Monad.Trans.State
data InterpError = InterpError () deriving (Show)
data Environment = Environment () deriving (Show)
data Op = Add deriving (Show)
data Value = Num Integer deriving (Show)
data Arithmic = ConstInteger Integer
| BinaryArithmicExpression Op Arithmic Arithmic
deriving (Show)
bArithHelper :: Arithmic -> Arithmic -> (Integer -> Integer -> Integer) -> EitherT InterpError (StateT Environment IO) Value
bArithHelper a b func = do
Num st1 <- interpArithmic a
Num st2 <- interpArithmic b
return $ Num $ func st1 st2
-- This function interpretes an arithmic expression and returns it's result.
-- An error message (int the form of Error) is returned in case something goes wrong.
interpArithmic :: Arithmic -> EitherT InterpError (StateT Environment IO) Value
interpArithmic (ConstInteger a) = return (Num a)
interpArithmic (BinaryArithmicExpression Add a b) = bArithHelper a b (\x -> \y -> x + y)
main :: IO ()
main = do
res <- runStateT (runEitherT $ interpArithmic (BinaryArithmicExpression Add (ConstInteger 2) (ConstInteger 3))) $ Environment ()
print res