我有一个中等大小的应用程序,Data.Acid用于持久性,我遇到了一种情况,我需要Update为下一版本的服务器更新我的一个事件的实现.即我有类似的东西
myUpdate :: Update MyState ()
myUpdate = <some outdated implementation>
Run Code Online (Sandbox Code Playgroud)
现在,显然我不能随意改变实现,因为它会破坏我的交易历史,所以我想知道人们通常如何处理这个问题.我看到它的方式是我的选择:
停止服务器.createCheckpoint为我而奔跑AcidState.更新Event实施,然后重新启动服务器.由于我们从新快照加载,因此更改Update不应该触发旧事件.
Update使用新名称(如myUpdate_v2)创建一个新的,并将我的服务器逻辑更新为仅使用myUpdate_v2到处而不是原始名称myUpdate.
我认为这两种选择都有其优点.(1)更好,因为我不需要在我的代码库中保留旧功能,但必须非常仔细地为我更新的每个服务器完成,否则我可能会破坏数据.(2)更安全(特别是如果我myUpdate从我的模块的导出中删除旧的,所以我可以确定我不小心在任何地方使用旧的实现),但它感觉有点难看.
有没有更好的方法来做到这一点?我认为这是我在一个长期项目中一定会遇到的事情,所以我希望有一个良好的标准工作流程来应用对事件实现的更改.
我最近遇到了一个Cabal问题,我只是通过在运行我的项目之前手动安装我的cabal沙箱中transformers-compat 的-f transformers3标志来解决这个问题cabal install.
有没有办法在我的应用程序的.cabal文件中指出我依赖于库,以便它使用特定的构建标志构建?
我遇到了一种情况,我的代码将受益于使用Functor和Applicative类似的抽象,但对于类型的类型(* -> *) -> *.定义一个更高级的仿函数可以RankNTypes像这样完成
class HFunctor f where
hfmap :: (forall x. a x -> b x) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)
但更高级的版本Applicative有点棘手.这是我能想到的最好的:
class HFunctor f => HApplicative f where
hpure :: (forall x. a x) -> f a
(<**>) :: f (a :-> b) -> f a -> f b
newtype (:->) a b x = HFunc (a x -> b x)
infixr 5 :->
Run Code Online (Sandbox Code Playgroud)
我们需要:-> …
我正在玩van Laarhoven镜头并遇到一个问题,其中类型检查器拒绝了et-reduced形式的良好类型的功能:
{-# LANGUAGE RankNTypes #-}
import Control.Applicative
type Lens c a = forall f . Functor f => (a -> f a) -> (c -> f c)
getWith :: (a -> b) -> ((a -> Const b a) -> (c -> Const b c)) -> (c -> b)
getWith f l = getConst . l (Const . f)
get :: Lens c a -> c -> a
get lens = getWith id lens
Run Code Online (Sandbox Code Playgroud)
上面的类型检查,但如果我eta减少get到
get :: Lens …Run Code Online (Sandbox Code Playgroud) 是否可以使用您自己的数据类型模拟具有GHC扩展名的函数?我想做的是例如
(假想的语法)
data MyFunc = MyFunc String (Int->Int)
instance (Int->Int) MyFunc where
($) (MyFunc _ f) i = f i
inc = MyFunc "increment" (1+)
test = inc 1Run Code Online (Sandbox Code Playgroud)
即带有一些元信息的数据,可以进行模式匹配,但仍可以像常规函数一样调用.现在,我知道我可以定义自己的中缀运算符$$和调用inc $$ 1,但是能够使用常规函数调用语法在嵌入式DSL中非常有用.
我正在尝试为长度索引列表实现一种拉链,它将返回列表中的每个项目以及删除该元素的列表.例如普通列表:
zipper :: [a] -> [(a, [a])]
zipper = go [] where
go _ [] = []
go prev (x:xs) = (x, prev ++ xs) : go (prev ++ [x]) xs
Run Code Online (Sandbox Code Playgroud)
以便
> zipper [1..5]
[(1,[2,3,4,5]), (2,[1,3,4,5]), (3,[1,2,4,5]), (4,[1,2,3,5]), (5,[1,2,3,4])]
Run Code Online (Sandbox Code Playgroud)
我目前尝试为长度索引列表实现相同的功能:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
data Nat = Zero | Succ Nat
type One = Succ Zero
type family (+) (a :: Nat) (b …Run Code Online (Sandbox Code Playgroud) 在我目前的项目中,我遇到了将各种monad变成变压器对应物的需求,例如
stateT :: Monad m => State s a -> StateT s m a
stateT stf = StateT $ return . runState stf
Run Code Online (Sandbox Code Playgroud)
为我需要的monad编写这些实用程序函数是微不足道的,但我想知道是否已经存在一个包含标准monad的这个功能的库,也许是一个抽象这种转换的类型类.就像是
class (Monad f, MonadTrans t) => LiftTrans f t | f -> t where
liftT :: Monad m => f a -> t m a
Run Code Online (Sandbox Code Playgroud)
("升力"可能是在这里使用的错误术语,但我不确定还有什么可以称之为.)
我试图绕过enumerator图书馆并遇到一种情况,我想用两个现有的Enumeratees构建一个新的Enumeratee.假设我有枚举:
e1 :: Enumeratee x y m b
e2 :: Enumeratee y z m b
Run Code Online (Sandbox Code Playgroud)
我觉得我应该能够将它们组合成一个枚举器
e3 :: Enumeratee x z m b
Run Code Online (Sandbox Code Playgroud)
但我在包中找不到现有的功能.我自己尝试编写这样一个函数,但是我对iteratees的理解仍然非常有限,以至于我无法找到一种方法来匹配所有复杂的类型.
我是否只是错过了一些基本的组合器,或者是枚举器甚至应该可以相互组合?
我已经阅读了箭头符号文档页面,但我并不完全清楚"7.10.3.定义自己的控制结构"中使用的"管道括号"是什么.
鉴于上述文件中的例子
proc x -> do
y <- f -< x+1
(|untilA (increment -< x+y) (within 0.5 -< x)|)
Run Code Online (Sandbox Code Playgroud)
没有使用箭头符号的等效代码是什么?
文本文件包含两列 - 索引号(5个空格)和字符(30个空格).它按字典顺序排列.我想执行二进制搜索来搜索关键字.
haskell ×9
acid-state ×1
applicative ×1
arrows ×1
binary ×1
cabal ×1
data-kinds ×1
functor ×1
iterate ×1
python ×1
search ×1
syntax ×1
text-files ×1
types ×1