小编jak*_*iel的帖子

整理Monad - 将monad变换器的应用转换为newtype monad

我试图采取例如ExceptT a (StateT A M),对于一些具体类型A和monad M,并将它们包装到我的新自定义monad中.

首先,我确定了StateT A M在其他环境中经常出现,因此我决定这将是最好的单独包装在一个单子M1,然后包装ExceptT a M1M2.

所需的属性是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和 …

haskell state-monad monad-transformers newtype lifting

9
推荐指数
1
解决办法
547
查看次数

使用GHC作为库

通过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)

api haskell ghci

7
推荐指数
1
解决办法
196
查看次数

有状态循环与不同类型的休息

我试图将以下有状态命令代码转换为Haskell.

while (true) {
  while (get()) {
    if (put1()) {
      failImmediately();
    }
  }
  if (put2()) {
    succeedImmediately();
  }
}
Run Code Online (Sandbox Code Playgroud)

无论是put1put2读取系统的状态,并对其进行修改.get可以简单地读取状态.failImmediately应该突破无限循环并呈现一种结果,succeedImmediately也应该突破却呈现出不同的结果.

我试图用是State Env Result其中Env代表环境的状态,Result是像Either Failure Success一些定制FailureSuccess.

我挣扎着要求整个结果表达式应该崩溃到Failure/ Success一旦它们中的一个产生(打破循环),否则继续前进.

我有一个想法是利用Either Exit ()地方data Exit = Success | Failure和使用StateT某种方式在表现Left对的Either,就好像Either是被链接的单子,也就是忽略任何后续行动.

我真的很感激haskell代码的任何灵感或样本,它将实现与上面的代码片段相同的行为.

编辑:精炼版移动到一个单独的问题" 有不同类型的短路的状态计算(可能,或者) ".

monads haskell state-monad monad-transformers

5
推荐指数
1
解决办法
150
查看次数

预制monad变压器

假设我有两个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)

monads haskell composition monad-transformers

5
推荐指数
1
解决办法
158
查看次数

不同类型短路的状态计算(也许,要么)

我试图找到将以下有状态命令式代码段转换为纯函数表示的最优雅方式(最好在 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

4
推荐指数
1
解决办法
628
查看次数

展平monad堆栈

所以我在第一个严肃的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单独操作?

monads haskell monad-transformers lifting

4
推荐指数
1
解决办法
530
查看次数

在Haskell类型族中键入歧义

我正在尝试将以下类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)

haskell type-inference type-families

4
推荐指数
1
解决办法
148
查看次数

包含在IO中的惰性列表

假设代码

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 lazy-evaluation io-monad

3
推荐指数
1
解决办法
305
查看次数