我正在研究基于约束的搜索的自动边界.因此,我的出发点是SEND MORE MONEY问题,基于非确定性选择的解决方案无需替换.我已经修改了方法来计算执行的样本数量,以便更好地衡量添加约束对搜索的影响.
import Control.Monad.State
import Control.Monad.Trans.List
import Control.Monad.Morph
import Data.List (foldl')
type CS a b = StateT [a] (ListT (State Int)) b
select' :: [a] -> [(a, [a])]
select' [] = []
select' (x:xs) = (x, xs) : [(y, x:ys) | ~(y, ys) <- select' xs]
select :: CS a a
select = do
i <- lift . lift $ get
xs <- get
lift . lift . put $! i + length …Run Code Online (Sandbox Code Playgroud) 我是hackage,lrucache包的维护者.我最近收到了为Binary和添加实例的功能请求NFData.这些都是有用的东西,原则上我对这些实例没有任何问题.
但是,它们都引入了新的包依赖关系,我希望尽可能减少我的包的依赖列表.有理智的方法来处理这个问题吗?可能有二十多个不同的包提供了lrucache可以实现的数据结构的有用类型类,并从中获得了一些好处.
显然,将所有这些作为依赖项添加是非启动性的.但还有什么可以做呢?
我可以向lrucache.cabal添加标志,以便编译各种实例.这样做可以使依赖列表最小化,除非您需要它.但它在现实世界中是可怕的,因为你无法在build-depends部分中指定构建标志.因此,您可以依赖具有特定标志的包,但不指定该依赖关系.这很快就会减少到无用的程度.
我可以创建一堆孤立实例包.这样做的好处是可以在build-depends部分中指定对这些实例的依赖性.它的主要缺点是在hackage中添加了大量额外的包,并且需要将它们作为单独的包维护.
我还可以做些什么?什么是正确的做法?
我是一个Haskell新手,我认为我理解monad和他们的机制(至少对于列表,州,也许,作家和读者monad),但我想理解为什么他们已经按照他们的方式定义,或者为什么他们必须是他们的方式,以帮助我思考他们的直觉.
具体来说,阅读是什么让读者或状态monad需要是函数(即\s -> (a,s)),而不仅仅是像作者monad(ie (w,a))这样的数据?
另外,编写器monad可以用作状态monad,其中日志用作状态的字符串表示,只要MonadPlus不使用该功能?与编写器monad一起使用的monadic函数是否允许查看当前日志并随意修改,或者只是编写器monad的bind函数允许查看日志?
另外,为什么monad是用monadic函数定义的a -> m b,而不是类型m a -> mb?函数从基类型转换为monad包装类型有什么自然意义?
谢谢你的回答.
当我在Haskell中编写更大的程序时,我发现自己经常遇到问题.我发现自己经常需要多个不同的类型,这些类型共享内部表示和几个核心操作.
有两种相对明显的方法可以解决这个问题.
一个是使用类型类和GeneralizedNewtypeDeriving扩展名.将足够的逻辑放入类型类中以支持用例所需的共享操作.创建具有所需表示的类型,并为该类型创建类型类的实例.然后,对于每个用例,使用newtype为它创建包装器,并派生公共类.
另一种是使用幻像类型变量声明类型,然后使用EmptyDataDecls为每个不同的用例创建不同的类型.
我主要关心的不是混合共享内部表示和操作的值,而是在我的代码中有不同的含义.这两种方法都解决了这个问题,但感觉非常笨拙.我的第二个问题是减少所需的样板量,两种方法都做得很好.
每种方法的优点和缺点是什么?是否有一种技术更接近于我想做的事情,提供没有样板代码的类型安全?
id :: a -> a
liftM2 :: (Monad m) => (a -> b -> c) -> m a -> m b -> m c
ap :: (Monad m) => m (a -> b) -> m a -> m b
ap = liftM2 id
Run Code Online (Sandbox Code Playgroud)
你能帮忙解释一下应用ap时的推断类型吗?此外,问同等问题是否有效,但更具体地说,在这种情况下如何减少?liftM2id(a -> b -> c) -> m am (a -> b)