标签: monad-transformers

Linter说多余的lambda,但如果按照建议更换它会产生不同的错误

我正在阅读真实世界哈斯克尔 - 第10章.

所有函数都有共同类型L.ByteString -> Maybe (a, L.ByteString) 所以然后我查看了StateT定义,s -> m (a, s)如果它被写入,它与上面的内容完全匹配StateT L.ByteString Maybe a.所以我决定使用monad变换器重写第一个例子.希望如此

parseP5 :: StateT L.ByteString Maybe Greymap
parseP5 = do
   matchHeader (L8.pack "P5")
   skipSpace
   width <- getNat
   skipSpace
   height <- getNat
   skipSpace
   maxGrey <- getNat
   skipSpace
   _ <- getBytes 1
   bitmap <- getBytes (width*height)
   return (Greymap width height maxGrey bitmap)
Run Code Online (Sandbox Code Playgroud)

会工作的.

例如,matchHeader功能将成为

matchHeader :: L.ByteString -> StateT L.ByteString Maybe ()
matchHeader prefix = \str ->
      if …
Run Code Online (Sandbox Code Playgroud)

haskell monad-transformers

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

Haskell:替换monad变换器堆栈中的mapM以实现惰性求值(没有空间泄漏)

已经讨论过,mapM这里本来就不是懒惰的,例如这里这里.现在我正在努力解决这个问题的变化,其中mapM问题是在monad变换器堆栈内部.

这是一个函数,它取自我在gist.github.com上使用的LevelDB的具体,工作(但是空间泄漏)的例子:

-- read keys [1..n] from db at DirName and check that the values are correct
doRead :: FilePath -> Int -> IO ()
doRead dirName n = do
    success <- runResourceT $ do
        db <- open dirName defaultOptions{ cacheSize= 2048 }
        let check' = check db def in        -- is an Int -> ResourceT IO Bool
            and <$> mapM check' [1..n]      -- space leak !!!
    putStrLn $ if …
Run Code Online (Sandbox Code Playgroud)

monads haskell lazy-evaluation monad-transformers

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

如何通过 monad 转换器参数化 monad?

我想编写一种可以通过其 monad 转换器参数化的类型。我尝试了几件事,最终得到了一些类似的东西:

newtype Foo t a = Foo { unFoo :: t (State St) a }
Run Code Online (Sandbox Code Playgroud)

然后,我想要一堆实例:

deriving instance (MonadTrans t, Monad (t (State St))) => Monad (Foo t)
Run Code Online (Sandbox Code Playgroud)

最后,我使用适当的 monad 转换器实例化类型。我的代码类型检查,但我收到所有派生实例的警告:“没有明确的实现>>=”。如果我尝试运行它,当它遇到类型类函数时会出现未定义的错误。

有没有办法自动派生我需要的所有实例?我试图派生出更多的类,而不仅仅是Monad.

我也对一种更符合人体工程学的方式来完成同样的事情感兴趣——我必须不​​断手动包装和解开Foo构造函数,特别是当我尝试对其lift进行计算时,因为我无法弄清楚如何实现一个MonadTrans实例为了它。

monads haskell monad-transformers

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

没有因使用“tell”而产生 (MonadWriter [Log] IO) 的实例

考虑这个关于和 的玩具练习:我们需要根据一组预定义的规则过滤数据包列表。我们还需要根据另一组规则记录一些数据包。现在考虑两个增强功能:WriterWriterT

  1. 如果出现重复的连续数据包(满足记录标准),我们应该只创建 1 个日志条目,并打印重复计数。(目标是教授所谓的“延迟记录”技巧。)
  2. 我们需要为每个日志条目附加时间戳。(即使用WriterT w IO

我已经实现了 1,但我坚持将其扩展为 2。首先,下面是 1 的代码。该merge函数处理当前数据包,但将潜在的日志条目传递到下一步,该步骤将决定是否打印它或合并它:

import Control.Monad
import Data.List
import Control.Monad.Writer

type Packet = Int
data Log = Log {
    packet :: Packet,
    acceptance :: Bool,
    bulk :: Int
  } deriving Show

instance Eq Log where
  (==) a b = packet a == packet b

incr :: Log -> Log
incr x = x {bulk = 1 + bulk x}

shouldAccept :: …
Run Code Online (Sandbox Code Playgroud)

monads haskell monad-transformers

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

为什么 IO 不是 State 的实例化?

当我们有 时,为什么不IO实例化(严格)单子,如 中所提供的?我认为我们应该是代表现实本身的神奇类型。StateRealWorldControl.Monad.STRealWorld

我的意思是,回想一下 monad 的“run”函数State

runState :: (s -> (a, s)) -> s -> a
Run Code Online (Sandbox Code Playgroud)

将其实例化为RealWorld,我们得到:

runIO :: (RealWorld -> (a, RealWorld)) -> RealWorld -> a
Run Code Online (Sandbox Code Playgroud)

RealWorld 由于无论如何我们都无法构造 的值,因此这不应该充当像 那样的后门unsafePerformIO

原因是因为这种解释将启用 monad 转换器IOT,定义为StateT RealWorld

io monads state haskell monad-transformers

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

理解 Haskell 中的 RWST

我研究了这个,试图理解几个转换器单子如何相互作用,特别是更好地理解单子lift并与单子堆叠

对于这里找到的 RWST monad (我认为这是最好的文档),它是一个堆叠的 monad,其中 Reader、Writer、State 都是一个 Monadic 层(并且按照堆叠顺序)。或者说应该如何理解呢?当我查看定义时,runRWST :: r -> s -> m (a, s, w)我将其理解为将读取器环境作为状态环境并将任何单子包装在 的m返回值周围RWS。这也意味着这个monad中只存在两层monad。即外部 monadm和包含多个 monad 的元组。

这反过来也意味着您只能使用lift一次。将读取器状态单子中的值提升到外部单子中。

从这个意义上说get, 和ask只是应用两个内部单子之一的两个函数。对于最后一点,我仍然不确定我是否理解为什么即使阅读了这篇 stackoverflow 帖子,您仍然需要一个reader和一个state -monad 。我猜读者只对只读有意义,但如果不希望这样,可以在两个单独的状态单子周围使用变压器单子吗?

一个例子:

这些评论让我有理由思考并使以下内容更加明确......以下类型定义的内部单子和外部单子是什么?它本身是RWST一个包裹着(因此是外部单子)Either String(内部单子)的单子吗?

type MyRWST a = RWST
                 (String -> Either String …
Run Code Online (Sandbox Code Playgroud)

monads haskell functional-programming state-monad monad-transformers

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

StateT newtype:从mtl切换到变换器

使用mtl,派生MonadState似乎可以使状态操作正常解除:


:set -XGeneralizedNewtypeDeriving
import Control.Applicative (Applicative)
import Control.Monad.Trans ( MonadIO, liftIO )
import Control.Monad.State (MonadState, evalStateT, modify, StateT, gets)

data State = State { int:: Int }
newtype St a = St { unSt :: StateT State IO a } deriving (Functor, Applicative, Monad, MonadIO, MonadState State)

let testLift = gets int >> return () :: St ()
Run Code Online (Sandbox Code Playgroud)

对于变形金刚,没有MonadState


:set -XGeneralizedNewtypeDeriving
import Control.Monad.Trans.State.Strict (runStateT, evalStateT, modify, StateT, gets)
import Control.Monad.IO.Class ( MonadIO, liftIO )
import Control.Applicative (Applicative)


data State = State …
Run Code Online (Sandbox Code Playgroud)

haskell monad-transformers

0
推荐指数
1
解决办法
495
查看次数

使用Haskell将factorial写为命令函数

我在Haskell中编写了以下代码:

import Data.IORef
import Control.Monad
import Control.Monad.Trans.Cont
import Control.Monad.IO.Class
fac n = do
          i<-newIORef 1
          f<-newIORef 1
          replicateM_ n $ do
            ri<-readIORef i
            modifyIORef f (\x->x*ri)
            modifyIORef i (+1)
          readIORef f
Run Code Online (Sandbox Code Playgroud)

这是非常好的代码,它将factorial实现为命令式函数.但是replicateM_无法完全模拟真实for循环的使用.所以我尝试使用continuation创建一些东西,但我在这里失败的是我的代码:

ff = (`runContT` id) $ do
       callCC $ \exit1 -> do
         liftIO $ do
           i<-newIORef 1
           f<-newIORef 1
         callCC $ \exit2 -> do
           liftIO $ do 
             ri<-readIORef i
             modifyIORef (\x->x*ri)
             modifyIORef i (+1)
             rri<-readIORef i
             when (rri<=n) $ exit2(())
         liftIO $ do
           rf<-readIORef f
           return rf
Run Code Online (Sandbox Code Playgroud)

你能帮我纠正我的代码吗?谢谢

continuations haskell monad-transformers

0
推荐指数
1
解决办法
351
查看次数

Haskell StateT和ExceptT链

我不是很好的哈斯克尔程序员.我的任务是在我的大学编写一个编译器,我选择了haskell,因为它是用于此目的的好工具.我使用monads StateT和ExcepT,所以我有类型:

type Runner r s = StateT s (ExceptT LatteError IO) r
type RT r s = IO (Either LatteError (r, s))
Run Code Online (Sandbox Code Playgroud)

我用它创建walk一个程序树并生成asm代码,它可以按我的意愿工作.作为在树上行走的主要功能我使用

rProgram :: Program -> Runner [String] CompileState
Run Code Online (Sandbox Code Playgroud)

并解压缩结果我使用的功能

runR program = runExceptT (runStateT (rProgram program) initialCompileState)
Run Code Online (Sandbox Code Playgroud)

我想要做的不是有一些验证器,如类型检查,身份存在检查,我知道写它们.让我告诉我

tcProgram :: Program -> Runner () TypeCheckState
ieProgram :: Program -> Runner () IdentExistanceState
Run Code Online (Sandbox Code Playgroud)

我想以优雅的方式运行它们,并且throwError指示失败.如何把像他们这样的很多功能放在一起?

monads haskell monad-transformers

0
推荐指数
1
解决办法
213
查看次数

Haskell的State Monad在哪里,如何使用?

我正在学习State Monad,并被告知它已不存在,第一个问题是为什么Haskell删除了它?

当我使用

import Data.Functor.Identity
import Control.Monad.Trans.State

type State s = StateT s Identity
Run Code Online (Sandbox Code Playgroud)

我懂了

Ambiguous occurrence ‘State’
    It could refer to
       either ‘Control.Monad.Trans.State.State’
           or ‘Main.State’,
Run Code Online (Sandbox Code Playgroud)

但是当我尝试时:t State,我什么也没找到。这是自相矛盾的,我想知道它是否存在?

最后,我自己写

newtype State s a = State { runState :: s -> (a, s) }
Run Code Online (Sandbox Code Playgroud)

但是我还需要其他一些功能,例如putget...它们在哪里。

使用:i get中,我发现MonadState,这是新的实施 State

monads haskell monad-transformers

0
推荐指数
1
解决办法
117
查看次数