我试图采取例如ExceptT a (StateT A M)
,对于一些具体类型A
和monad M
,并将它们包装到我的新自定义monad中.
首先,我确定了StateT A M
在其他环境中经常出现,因此我决定这将是最好的单独包装在一个单子M1
,然后包装ExceptT a M1
成M2
.
所需的属性是make M1
和的M2
实例MonadState
和类M
(假设它被调用MyMonadClass
).也M2
应该是一个实例MonadError
.
首先我从简单类型的同义词开始:
type MyState = StateT A M
type MyBranch a = ExceptT a MyState
Run Code Online (Sandbox Code Playgroud)
然后我想我会首先勾画实例声明(没有实现实例),这就是我第一次被卡住的地方.instance MonadState A (MyState)
似乎不是正确的语法.我以为我必须创建newtype MyState' a = StateT a M
然后type MyState = MyState A
(不要在没有必要的地方使用语言扩展).
然而,一旦我开始将同义词转换为newtype
声明,我开始失去与StateT A M
和 …
通过api将表达式发送到ghci进行评估和打印结果的最简单的例子是什么?我无法找到一个可行的完整示例.是的,我已经尝试了https://wiki.haskell.org/GHC/As_a_library,但我一直收到的错误并没有告诉我多少:no package state yet: call GHC.setSessionDynFlags
.无论我setSessionDynFlags
在哪里尝试任何参数,或者setContext
,我总是以错误结束.我目前有(不setXYZ
):
import GHC
import GHC.Paths ( libdir )
import GhcMonad
import Debugger
import DynFlags
import Outputable
import Language.Haskell.HsColour
import Language.Haskell.HsColour.Colourise
colour :: String -> String
colour = hscolour TTY defaultColourPrefs True True "" False
ghci :: IO ()
ghci = runGhc (Just libdir) $ do
r <- runStmt "[1, 2, 3]" RunToCompletion
case r of
RunOk ns -> do
mapM_ ( \n -> do
mty …
Run Code Online (Sandbox Code Playgroud) 我试图将以下有状态命令代码转换为Haskell.
while (true) {
while (get()) {
if (put1()) {
failImmediately();
}
}
if (put2()) {
succeedImmediately();
}
}
Run Code Online (Sandbox Code Playgroud)
无论是put1
和put2
读取系统的状态,并对其进行修改.get
可以简单地读取状态.failImmediately
应该突破无限循环并呈现一种结果,succeedImmediately
也应该突破却呈现出不同的结果.
我试图用是State Env Result
其中Env
代表环境的状态,Result
是像Either Failure Success
一些定制Failure
和Success
.
我挣扎着要求整个结果表达式应该崩溃到Failure
/ Success
一旦它们中的一个产生(打破循环),否则继续前进.
我有一个想法是利用Either Exit ()
地方data Exit = Success | Failure
和使用StateT
某种方式在表现Left
对的Either
,就好像Either
是被链接的单子,也就是忽略任何后续行动.
我真的很感激haskell代码的任何灵感或样本,它将实现与上面的代码片段相同的行为.
编辑:精炼版移动到一个单独的问题" 有不同类型的短路的状态计算(可能,或者) ".
假设我有两个monad变换器
T1 :: (* -> *) -> * -> *
T2 :: (* -> *) -> * -> *
Run Code Online (Sandbox Code Playgroud)
与实例
instance MonadTrans T1
instance MonadTrans T2
Run Code Online (Sandbox Code Playgroud)
还有一些
X :: (((* -> *) -> * -> *) -> ((* -> *) -> * -> *) -> * -> *)
Run Code Online (Sandbox Code Playgroud)
如
newtype X t1 t2 a b = X { x :: t1 (t2 a) b }
Run Code Online (Sandbox Code Playgroud)
我想为此定义一些东西
instance (MonadTrans t1, MonadTrans t2) => MonadTrans (X t1 t2) where
lift = X …
Run Code Online (Sandbox Code Playgroud) 我试图找到将以下有状态命令式代码段转换为纯函数表示的最优雅方式(最好在 Haskell 中使用其 Monad 实现提供的抽象)。但是,我还不擅长使用转换器等组合不同的 monad。在我看来,在学习如何自己做时,分析他人对此类任务的看法最有帮助。命令式代码:
while (true) {
while (x = get()) { // Think of this as returning Maybe something
put1(x) // may exit and present some failure representation
}
put2() // may exit and present some success representation
}
Run Code Online (Sandbox Code Playgroud)
当get
返回时Nothing
我们需要继续执行put2
,当get
返回时Just x
我们希望x
被传递给put1
并且仅在put1
失败或循环时才短路。基本上put1
并且put2
可能会终止整个事情或移动到以下语句以某种方式改变底层状态。get
可以成功并调用put1
和循环或失败并继续put2
。
我的想法是:
forever $ do
forever (get >>= put1)
put2
Run Code Online (Sandbox Code Playgroud)
为什么我要寻找这样的东西是因为 …
haskell functional-programming imperative-programming state-monad monad-transformers
所以我在第一个严肃的haskell项目中都有这样的代码:
f :: (MonadTrans t) => ExceptT () (t (StateT A B)) C
f = do mapExceptT lift $ do
lift $ do
...
lift $ do
...
r <- ...
...
return r
>>= \r -> ...
Run Code Online (Sandbox Code Playgroud)
关于我如何实现目标肯定会出现问题(可能有更简单的方法)但目前我有兴趣学习如何以更好的方式处理一堆monad变换器(如果有的话).这是我弄清楚如何进入r
上下文B
并将其提升到堆栈中更高的monad 的唯一方法.提升整个块而不是初始语句是我自己可以得到的.
我经常最终得到的是lift
我发现的链条,liftIO
如果深的monad是可以避免的IO
.我不知道其他monad的通用方法.
当他最终处理这样的堆栈时,是否存在可以遵循的模式,并且必须在某个级别提取一个值,在不同级别提取不同的值,将这些组合并影响这两个级别中的任何一个或者可能是另一个级别?
可以以某种方式操纵堆栈,既不会提升整个块(导致let
和绑定变量限定范围并限制在内部块),也不需要lift . lift . ... lift
单独操作?
我正在尝试将以下类Domain
及其实例放在一起TrivialDomain
{-# LANGUAGE TypeFamilies #-}
data Transition = Transition
class Domain d where
type Set d
type Engine d :: * -> *
top :: Engine d (Set d)
-- ...
complement :: Set d -> Engine d (Set d)
exclude :: Set d -> Set d -> Engine d (Set d)
-- ...
data TrivialDomain = TrivialDomain
instance Domain TrivialDomain where
type Set TrivialDomain = [Int]
type Engine TrivialDomain = IO
top = return [0..10]
-- …
Run Code Online (Sandbox Code Playgroud) 假设代码
f :: IO [Int]
f = f >>= return . (0 :)
g :: IO [Int]
g = f >>= return . take 3
Run Code Online (Sandbox Code Playgroud)
当我g
在ghci中运行时,它会导致stackoverflow.但我想也许它可以懒惰地评估并生产[0, 0, 0]
包装IO
.我怀疑这IO
是责备,但我真的不知道.显然以下工作:
f' :: [Int]
f' = 0 : f'
g' :: [Int]
g' = take 3 f'
Run Code Online (Sandbox Code Playgroud)
编辑:事实上我对拥有这么简单的功能不感兴趣f
,原始代码看起来更像是这样:
h :: a -> IO [Either b c]
h a = do
(r, a') <- h' a
case r of
x@(Left _) -> h …
Run Code Online (Sandbox Code Playgroud) haskell ×8
monads ×3
state-monad ×3
lifting ×2
api ×1
composition ×1
ghci ×1
io-monad ×1
newtype ×1