查看文档Control.Applicative,我注意到它们具有某些monad的实例声明(例如IO,Maybe特别是ST),但是没有MTL monad的实例,例如State和RWS.相反,它看起来像是WrappedMonad定义了一个通用类型,我猜测它是涵盖所有其他情况.
所以这是我的问题:
为什么没有ApplicativeMTL monad的实例?到目前为止,我自己能够找到的最好的答案是一个三年前的帖子,有人实现了这些实例,并被忽略了.
最终我希望能够以State一种适用的方式使用(如我所推荐的那样),但如果我不得不用WrappedMonad数据构造函数丢弃我的代码,那么它似乎不是一个胜利.我也可以不理会WrappedMonad完全,并定义Applicative实例自己,是为做了同样的方式IO,ST等等:在以下方面return与ap......但似乎愚蠢的为好.
我正在模拟一个4位微处理器.我需要跟踪寄存器,内存和运行输出(还有一个获取 - 执行周期计数器的奖励点).我已经设法在没有monad的情况下做到了这一点,但是一下子明确地传递那么多东西感觉很乱.函数定义也很混乱,冗长且难以阅读.
我试图用monad做这个,它只是不适合在一起.我尝试将所有单独的状态组件视为单一类型,但这给我留下了产生价值的问题.
State Program () -- Represents the state of the processor after a single iteration of the fetch execute cycle
Run Code Online (Sandbox Code Playgroud)
是唯一有意义的类型.但那时为什么甚至打扰?我尝试通过从我的复合类型中拉出字符串并将其作为值来对其进行分解
State Program' String
Run Code Online (Sandbox Code Playgroud)
除了我需要RUNNING输出这一事实外,它工作得很好.无论我做了什么,我都无法同时保持弦乐和状态.
现在我正在努力解决monad变形金刚问题.似乎我必须将所有不同级别的州分开.但我的脑袋快速爆炸.
StateT Registers (StateT Memory (State Output)) a =
StateT (registers -> (StateT Memory (State Output)) (a,registers))
StateT Registers (StateT Memory (State Output)) a =
StateT (registers -> (Memory -> (Output -> (((a,Registers),Memory),Output))))
Run Code Online (Sandbox Code Playgroud)
我还没有进入FEcycle计数器!
问题:
Haskell可以MonadState s在T1下面派生实例,但不是在T2其中是非常相似的类型.我应该以哪种方式修改代码,T2以便MonadState s可以自动派生实例?
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import Control.Monad.Reader
import Control.Monad.State
newtype T1 r s a =
T1 { runT1 :: ReaderT r (State s) a }
deriving (Monad, MonadReader r, MonadState s)
newtype T2 r s a =
T2 { runT2 :: StateT r (State s) a }
deriving (Monad, MonadState r, MonadState s)
Run Code Online (Sandbox Code Playgroud) " Scala中的功能编程 "一书演示了如下的纯函数随机数生成器的示例
trait RNG {
def nextInt: (Int, RNG)
}
object RNG {
def simple(seed: Long): RNG = new RNG {
def nextInt = {
val seed2 = (seed*0x5DEECE66DL + 0xBL) &
((1L << 48) - 1)
((seed2 >>> 16).asInstanceOf[Int],
simple(seed2))
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法看起来像
val (randomNumber,nextState) = rng.nextInt
Run Code Online (Sandbox Code Playgroud)
我确实得到了它是纯函数的部分,因为它返回下一个状态并将其留在API客户端上,以便nextInt在下次需要随机数时使用它来调用但我不明白的是' 第一个随机的怎么样生成数字,因为我们必须seed至少提供一次.
如果有另一个功能提升seed得到RNG?如果是这样,那么我们如何期望这个API的客户端知道它(因为在非功能实现中用户只是调用nextInt并且状态由API维护)
有人可以给出Scala中纯函数随机数生成器的完整示例,并且可能将它与状态Monad关联起来.
上下文:我需要编写一个主要是无状态的编译器,它将VM字节码转换为机器码.大多数VM命令都可以使用纯函数进行无状态转换,如下所示:
compilePop = ["mov ax, @sp", "dec ax", "mov @sp, ax"]
compile :: VM_COMMAND -> [String]
compile STACK_POP = compilePop
-- compile whole program
compileAll :: [VM_COMMAND] -> [String]
compileAll = flatMap compile
Run Code Online (Sandbox Code Playgroud)
但是有些命令需要插入标签,每次调用都应该是不同的.
我理解如何使用整个编译器的状态对象"global"来执行此操作:
compileGt n = [label ++ ":", "cmp ax,bx", "jgt " ++ label]
where label = "cmp" ++ show n
compile :: Int -> COMPILER_STATE -> VM_COMMAND -> (COMPILER_STATE, [String])
-- here state currently contains only single integer, but it will grow larger
compile lcnt STACK_POP …Run Code Online (Sandbox Code Playgroud) 我无法掌握在SIGINT信号上中断冗长的纯计算的正确方法.
在下面的简单示例中,我有slowFib一个模拟冗长计算的函数.当它在IOmonad中运行时,我可以用Cc终止它(使用异步生成worker).
但是,当我将计算放在MonadState, MonadIO堆栈中时,它不再起作用......另一方面,threadDelay在同一堆栈中的简单仍然可以终止.
代码如下:
{-# LANGUAGE FlexibleContexts #-}
module Main where
import Data.Monoid
import Control.DeepSeq
import Control.Concurrent
import Control.Concurrent.Async
import Control.Monad.State
-- import Control.Monad.State.Strict
import System.Posix.Signals
slowFib :: Integer -> Integer
slowFib 0 = 0
slowFib 1 = 1
slowFib n = slowFib (n - 2 ) + slowFib (n - 1)
data St = St { x :: Integer } deriving (Show)
stateFib :: (MonadState St m, MonadIO m) => …Run Code Online (Sandbox Code Playgroud) 我有一个计算,我在其中将值插入Map,然后再次查找它们。我知道我从来没有在插入密钥之前使用过密钥,但是(!)无论如何随意使用都会使我感到紧张。我正在寻找一种获取总查询功能的方法,该方法不会返回Maybe,并且类型系统可以防止我意外滥用。
我的第一个想法是制作一个类似于的monad转换器StateT,其中状态为a Map,并且在monad中有用于插入和查找的特殊功能。插入函数返回一个新类型Receipt s k,其中s是STmonad 样式的幻像索引类型,并且k是键的类型,而查找函数则使用a Receipt而不是裸键。通过隐藏Receipt构造函数并使用类似于的量化运行函数runST,这应确保查找仅在插入同一映射后发生。(完整代码如下。)
但是我担心我已经重新发明了轮子,或者担心有另外一种获取安全的总地图查找的方法。在某个地方的公共包装中是否存在针对此问题的任何现有技术?
{-# LANGUAGE DeriveFunctor, LambdaCase, RankNTypes #-}
module KeyedStateT (KeyedStateT, Receipt, insert, lookup, receiptToKey, runKeyedStateT)
where
import Prelude hiding (lookup)
import Control.Arrow ((&&&))
import Control.Monad (ap, (>=>))
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Maybe (fromJust)
newtype KeyedStateT s k v m a = KeyedStateT (Map k v -> …Run Code Online (Sandbox Code Playgroud) 我有一个递归函数,它接收一个包含多个字段的数据对象,例如:
data MyState = {
first :: Int,
second :: String,
third :: Bool,
...
}
type Result = Int
Run Code Online (Sandbox Code Playgroud)
这个递归函数在执行期间改变它并将它传递给自己以备下次执行。它看起来如下:
-- This is a pseudocode, just to give an idea about the workflow.
process :: MyState -> Result
process st = go st
where go st | first == 1 = (go . changeFunc1) st
| first == 2 = (go . changeFunc2) st
| otherwise = generateResult st
changeFunc1 :: MyState -> MyState
changeFunc1 st | third st …Run Code Online (Sandbox Code Playgroud) 我对 Haskell 相当陌生。我试图通过将任何一个视为 monad 来将 State monad 与错误传播结合起来。我想以不需要显式处理状态或错误的方式递归抽象语法树(例如,用于为语句和表达式编写解释器)。我的印象是,最简单的方法是使用 ExceptT monad 转换器。这是我编译的示例代码:
import Control.Monad.Except
import Control.Monad.State
import qualified Data.Map.Strict as M
-- simple expression language supporting crude let bindings
data Exp = Lit Int | Var String
| Add (Exp, Exp) | Let (String, Exp, Exp) deriving Show
okExp = -- let x = 2 in let y = x + 3 in x + y -- evaluate to 7
Let ("x", Lit 2,
Let ("y", Add (Var "x", Lit 3), …Run Code Online (Sandbox Code Playgroud) 定义索引 monad a la Atkey的常用方法是:
class IxMonad m where
ireturn :: a -> m i i a
ibind :: m i j a -> (a -> m j k b) -> m i k b
Run Code Online (Sandbox Code Playgroud)
另一种方法可以在McBride的工作中找到(他也在这里讨论过):
type f :-> g = forall i. f i -> g i
class MonadIx (m :: (state -> *) -> (state -> *)) where
returnIx :: f :-> m f
flipBindIx :: (f :-> m g) -> (m f …Run Code Online (Sandbox Code Playgroud) state-monad ×10
haskell ×9
monads ×5
applicative ×1
closures ×1
concurrency ×1
deriving ×1
dictionary ×1
either ×1
newtype ×1
scala ×1
signals ×1
st-monad ×1
state ×1