这里是评估文档的摘录:(参见http://hackage.haskell.org/packages/archive/base/4.5.0.0/doc/html/Control-Exception-Base.html#v:evaluate)
Run Code Online (Sandbox Code Playgroud)Control.Exception.Base.evaluate :: a -> IO a
是不一样的
Run Code Online (Sandbox Code Playgroud)evaluate x
一个正确的定义是
Run Code Online (Sandbox Code Playgroud)return $! x
我不明白这两个定义之间的语义差异......是否有人可以帮助我?提前致谢!
我有一些代码目前使用ST monad进行评估.我不喜欢将IO放在任何地方,因为该runST
方法产生纯粹的结果,并指示这样的结果可以安全地调用(相对unsafePerformIO
).但是,由于我的一些代码变得更长,我确实希望将调试打印语句放入.
是否有任何类提供双重个性monad [或类型类机制],可以是ST或IO(取决于其类型或"isDebug"标志)?我记得SPJ在他的"Fun with Type Functions"论文中引入了一个"Mutation"类,它使用关联类型将IO与IORef和ST关联到STRef.这样的包存在某个地方吗?
非常感谢[第n次],CA McCann!使用该解决方案,我能够为支持pdebug
函数的monad引入一个额外的类.该ST
单子会忽略这些呼叫,而IO
将运行putStrLn
.
class DebugMonad m where
pdebug :: String -> m ()
instance DebugMonad (ST s) where
pdebug _ = return ()
instance DebugMonad IO where
pdebug = putStrLn
test initV = do
v <- newRef initV
modifyRef v (+1)
pdebug "debug"
readRef v
testR v = runST $ test v
Run Code Online (Sandbox Code Playgroud)
这在ghci中有一个非常幸运的结果.由于默认情况下表达式是IO类型,因此运行类似"test 3"的操作将导致IO monad运行,因此您可以轻松地调试它,然后在您真正想要运行时使用类似"testR"的方法调用它它.
我只是在学习Haskell和IO monads.我想知道为什么这不会强制程序输出"hi"以及"bye":
second a b = b
main = print ((second $! ((print "hi") >>= (\r -> return ()))) "bye")
Run Code Online (Sandbox Code Playgroud)
据我所知,$!
运算符会强制要求第一个参数second
进行求值,并且>>=
运算符需要运行print "hi"
以便从中获取值并将其传递\r -> return ()
给屏幕,这将打印"hi"到屏幕.
我的推理有什么问题?
而且,有没有办法证明Haskell不能被欺骗(除了使用不安全的函数)在"安全"代码中运行IO操作?
无论好坏,Haskell流行的Servant库使得在monad变换器堆栈中运行代码变得很普遍ExceptT err IO
.仆人自己的处理程序monad是ExceptT ServantErr IO
.正如许多人所说,这是一个有点麻烦的monad工作,因为有多种方法可以展开失败:1)通过IO
基地的正常例外,或2)返回Left
.
正如Ed Kmett的exceptions
图书馆有助于澄清:
基于连续的monad和诸如
ErrorT e IO
提供多种故障模式的堆栈是this [MonadMask
]类的无效实例.
这非常不方便,因为MonadMask
我们可以访问有用的[多态版本] bracket
函数来进行资源管理(不会因异常而泄漏资源等).但是在Servant的Handler
monad我们不能使用它.
我对它不是很熟悉,但是有些人说解决方案是使用monad-control
它和许多合作伙伴库一样,lifted-base
并且lifted-async
让你的monad访问资源管理工具bracket
(大概这适用于ExceptT err IO
和朋友一样?).
然而,似乎monad-control
是失去了在社会上赞成,但我不能告诉替代将是什么.即使Snoyman最近的safe-exceptions
图书馆使用Kmett的exceptions
库也避免了monad-control
.
有人可以为像我这样试图为严重的Haskell使用方式的人们澄清当前的故事吗?
resources haskell exception-handling monad-transformers io-monad
首先,我为非描述性标题道歉.由于我不知道实际发生了什么,所以我无法让它更具体.
现在我的问题.我已经为99个Haskell问题中的问题23实现了以下代码段,它应该n
从列表中随机选择项目:
rndSelect' :: RandomGen g => [a] -> Int -> g -> ([a], g)
rndSelect' _ 0 gen = ([], gen)
rndSelect' [] _ _ = error "Number of items requested is larger than list"
rndSelect' xs n gen = ((xs !! i) : rest, gen'')
where (i, gen') = randomR (0, length xs - 1) gen
(rest, gen'') = (rndSelect' (removeAt xs i) (n - 1) gen')
rndSelectIO' :: [a] -> Int -> IO …
Run Code Online (Sandbox Code Playgroud) 以下代码有点神秘.在非玩具版本的问题中,我试图在monad Result中进行monadic计算,其值只能在IO中构造.似乎IO背后的魔力使这样的计算严格,但我无法弄清楚究竟是怎么发生的.
代码:
data Result a = Result a | Failure deriving (Show)
instance Functor Result where
fmap f (Result a) = Result (f a)
fmap f Failure = Failure
instance Applicative Result where
pure = return
(<*>) = ap
instance Monad Result where
return = Result
Result a >>= f = f a
Failure >>= _ = Failure
compute :: Int -> Result Int
compute 3 = Failure
compute x = traceShow x $ Result x
compute2 :: Monad …
Run Code Online (Sandbox Code Playgroud) Haskell中的可变载体有三个元素级变异器:
read :: PrimMonad m => MVector (PrimState m) a -> Int -> m a
write :: PrimMonad m => MVector (PrimState m) a -> Int -> a -> m ()
swap :: PrimMonad m => MVector (PrimState m) a -> Int -> Int -> m ()
Run Code Online (Sandbox Code Playgroud)
现在我可以使用这些 -
import Data.Vector
import Data.Vector.Mutable
import Control.Monad.ST
import Control.Monad.Primitive
incrAt :: Vector Double -> Int -> Vector Double
incrAt vec i = runST $ do
mvec <- thaw vec
oldval <- read …
Run Code Online (Sandbox Code Playgroud) 我看过algo.monads和fluokitten文档.我还阅读了Jim Duey,Konrad Hinsen和Leonardo Borges的 monad博客文章.
我能找到的最接近的是Konrad Hinsen的图书馆Monadic IO流 - 但这似乎并没有'实现monad接口'(因为想要更好的措辞)
这是在Haskell中使用ST的示例
oneST :: ST s Int -- note that this works correctly for any s
oneST = do var <- newSTRef 0
modifySTRef var (+1)
readSTRef var
one :: Int
one = runST oneST
Run Code Online (Sandbox Code Playgroud)
为了测试我在Haskell的技能,我决定实现你在Land of Lisp/Realm of Racket中找到的第一款游戏.在"猜猜我的号码"的游戏.游戏依赖于可变状态来运行,因为它经常需要更新程序的上限和下限以回归用户正在考虑的值.
它有点像这样:
> (guess)
50
> (smaller)
25
> (bigger)
37
Run Code Online (Sandbox Code Playgroud)
现在,这种事情(据我所知)在Haskell中完全不可能,从REPL中调用一些修改全局可变状态的函数,然后立即打印结果,因为它违反了不变性原则.因此,所有交互必须存在于IO
和/或State
monad中.那就是我被困住的地方.
我似乎无法将我的想法包含在IO
monad和State
monad的组合中,所以我可以获得输入,打印结果和修改状态,所有这些都在同一个函数中.
这是我到目前为止所得到的:
type Bound = (Int, Int) -- left is the lower bound, right is the upper
initial :: Bound
initial = (1, 100)
guess :: Bound -> Int
guess (l, u) = (l + u) `div` 2
smaller :: State Bound ()
smaller = do
bd@(l, _) <- get …
Run Code Online (Sandbox Code Playgroud) 当我查看scalaz.effect.IO
源代码时,我注意到它有一个apply
带有以下签名的方法:
sealed trait IO[A] {
def apply(rw: Tower[IvoryTower]): Trampoline[(Tower[IvoryTower], A)]
}
Run Code Online (Sandbox Code Playgroud)
Tower[A]
并IvoryTower
定义为:
case class Tower[A]()
sealed trait IvoryTower
Run Code Online (Sandbox Code Playgroud)
有一个例子Tower
:
object IvoryTower extends IvoryTowers
trait IvoryTowers {
val ivoryTower = Tower[IvoryTower]()
}
Run Code Online (Sandbox Code Playgroud)
这些课程的目的是什么?为什么IO.apply
接受类型的参数Tower[IvoryTower]
?
io-monad ×10
haskell ×9
monads ×5
st-monad ×2
clojure ×1
evaluation ×1
io ×1
resources ×1
scala ×1
scalaz ×1
state-monad ×1
strictness ×1
traversal ×1
typeclass ×1