标签: free-monad

是否可以使用Free在DSL中实现多态函数

我正在使用Free Monads构建一个小型DSL.

我希望能够在我的DSL中拥有多态功能.

我想要构建的一个例子是:

{-# LANGUAGE TemplateHaskell #-}

import           Control.Monad.Free.Church

data Queue a = Queue a

data MyDsl next =
  NewQueue (Queue a -> next) |
  WriteToQueue (Queue a) a next

makeFree ''MyDsl

testProgram :: F MyDsl
testProgram = do
  (intQueue :: Queue Int) <- newQueue
  (charQueue :: Queue Char) <- newQueue
  writeToQueue intQueue 1
  writeToQueue charQueue 'c'
Run Code Online (Sandbox Code Playgroud)

我编码它的方式我得到的Not in scope: type variable ‘a’ 错误是有道理的.有没有办法在使用Free的DSL中拥有多态函数?

对于背景,我想这样做的原因是我可以拥有一个在幕后使用TQueue的生产解释器和一个使用内存数据结构进行测试的测试解释器.

dsl haskell free-monad

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

Free~> Trampoline:OutOfMemoryError的递归程序崩溃

假设我只尝试使用一个操作来实现一个非常简单的特定于域的语言:

printLine(line)
Run Code Online (Sandbox Code Playgroud)

然后我想写一个程序,它接受一个整数n作为输入,打印一些东西,如果n可以被10k整除,然后调用自己n + 1,直到n达到一些最大值N.

省略由for-comprehensions引起的所有语法噪音,我想要的是:

@annotation.tailrec def p(n: Int): Unit = {
  if (n % 10000 == 0) printLine("line")
  if (n > N) () else p(n + 1)
}
Run Code Online (Sandbox Code Playgroud)

从本质上讲,它将是一种"fizzbuzz".

以下是使用Scalaz 7.3.0-M7中的Free monad实现此操作的一些尝试:

import scalaz._

object Demo1 {

  // define operations of a little domain specific language
  sealed trait Lang[X]
  case class PrintLine(line: String) extends Lang[Unit]

  // define the domain specific language as the free monad of operations
  type …
Run Code Online (Sandbox Code Playgroud)

scala tail-recursion out-of-memory scalaz free-monad

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

FreeT的MonadTransControl实例

是否可以为实现一个MonadTransControl实例FreeT?我从以下内容开始,但陷入困境:

instance (Functor f) => MonadTransControl (FreeT f) where
  newtype StT (FreeT f) r = FreeTStT r
  liftWith unlift = lift $ unlift $ error "Stuck here"
  restoreT inner = do
    FreeTStT r <- lift inner
    return r
Run Code Online (Sandbox Code Playgroud)

如果它无法实现,那么为什么并且可以通过某种方式扩展特定的自由函子实现以使其可以实现?

haskell monad-transformers free-monad

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

变焦和免费monad很难

我正在使用免费的monad和镜头,使用免费的monad来创建我自己的IO monad版本:

data MyIO next
    = LogMsg String next
    | GetInput (String -> next)
    deriving (Functor)
Run Code Online (Sandbox Code Playgroud)

我把它堆叠在状态monad之上,如下所示:FreeT MyIO (State GameState) a其中GameState:

data GameState = GameState { _players :: [PlayerState] }
Run Code Online (Sandbox Code Playgroud)

现在,我想要的是一种PlayerStateGameState上下文"放大"a 的方法.像这样的东西:

zoomPlayer :: Int -> FreeT MyIO (State PlayerState) a -> FreeT MyIO (State GameState) a
zoomPlayer i prog = hoistFreeT (zoom (players . element i)) prog
Run Code Online (Sandbox Code Playgroud)

但是我收到了这个错误:

No instance for (Data.Monoid.Monoid a1)
  arising from a use of ‘_head’
Run Code Online (Sandbox Code Playgroud)

这个错误似乎与players …

haskell state-monad free-monad haskell-lens

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

解析为免费Monad

说我有以下免费monad:

data ExampleF a
  = Foo Int a
  | Bar String (Int -> a)
  deriving Functor

type Example = Free ExampleF  -- this is the free monad want to discuss
Run Code Online (Sandbox Code Playgroud)

我知道如何使用此monad。我可以写一些不错的助手:

foo :: Int -> Example ()
foo i = liftF $ Foo i ()

bar :: String -> Example Int
bar s = liftF $ Bar s id
Run Code Online (Sandbox Code Playgroud)

所以我可以用haskell编写程序,例如:

fooThenBar :: Example Int
fooThenBar =
  do
    foo 10
    bar "nice"
Run Code Online (Sandbox Code Playgroud)

我知道如何打印,解释等。但是如何解析呢?

是否有可能编写一个解析器来解析任意程序,例如:

foo 12
bar nice
foo 11
foo …
Run Code Online (Sandbox Code Playgroud)

monads haskell string-parsing free-monad

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

在最不固定类型之后的haskell中的bifunctor

我不确定如何在定点之后派生出函数实例:

data FreeF f a next  = PureF a | FreeF (f next)  deriving (Functor)

data Mu f  = In { out :: f ( Mu f ) }

newtype Free f a = Free(  Mu (FreeF f a)  )

instance Functor f => Functor (Free f) where
     fmap h (Free (out -> PureF a))  = Free (In (PureF (h a)))
     fmap h (Free (out -> FreeF fn)) = Free (In (fmap undefined undefined)) --stuck
Run Code Online (Sandbox Code Playgroud)

如果我修改Mu以接受额外的类型参数,我可以继续...直到...:

data Mu f a …
Run Code Online (Sandbox Code Playgroud)

haskell functor recursive-datastructures free-monad

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

加宽ocaml中的类型

我试图在ocaml中编写一个免费的monad库,跟随haskell的Control.Monad.Free,但是我在一个点上,在hoistFree的实现中陷入困境.

hoistFree :: Functor g => (forall a. f a -> g a) -> Free f b -> Free g b
hoistFree _ (Pure a)  = Pure a
hoistFree f (Free as) = Free (hoistFree f <$> f as)
Run Code Online (Sandbox Code Playgroud)

这是我翻译的尝试.

let rec hoistfree : 'b.('b t -> 'b t) -> 'a m -> 'a m =
      fun f x -> match x with
       | Return x -> Return x
       | Free x   -> Free (T.map (hoistfree f) (f …
Run Code Online (Sandbox Code Playgroud)

monads ocaml haskell free-monad

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

带有 Coproduct 和 monad 转换器的 Scala Free Monads

我正在尝试在我的项目中开始使用免费的 monad,我正在努力让它变得优雅。
假设我有两个上下文(实际上我有更多) -Receipt而且User- 都对数据库进行了操作,我希望将它们的解释器分开并在最后一刻组合它们。
为此,我需要为每个操作定义不同的操作,并使用Coproduct.
这是我经过几天的谷歌搜索和阅读后的结果:

  // Receipts
sealed trait ReceiptOp[A]
case class GetReceipt(id: String) extends ReceiptOp[Either[Error, ReceiptEntity]]

class ReceiptOps[F[_]](implicit I: Inject[ReceiptOp, F]) {
  def getReceipt(id: String): Free[F, Either[Error, ReceiptEntity]] = Free.inject[ReceiptOp, F](GetReceipt(id))
}

object ReceiptOps {
  implicit def receiptOps[F[_]](implicit I: Inject[ReceiptOp, F]): ReceiptOps[F] = new ReceiptOps[F]
}

// Users
sealed trait UserOp[A]
case class GetUser(id: String) extends UserOp[Either[Error, User]]

class UserOps[F[_]](implicit I: Inject[UserOp, F]) {
  def getUser(id: String): Free[F, Either[Error, User]] = …
Run Code Online (Sandbox Code Playgroud)

scala monad-transformers free-monad scala-cats

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

使用 Haskell monad“do”表示法定义语法树

我正在尝试构建一个抽象语法树,允许使用 monaddo表示法进行定义,如下所示:

ast = do
    Variable uint8 "i"
    Function Void "f" $ do
        Variable uint8 "local_y"
        Comment "etc. etc."
Run Code Online (Sandbox Code Playgroud)

我在这里展示的结构是从Text.Blaze.Html中收集的,它用于定义 HTML 树。

问题分散在以下各个部分。主要问题是如何正确地做到这一点。当然,任何有助于理解此结构的输入都将受到高度赞赏。

因此,首先,这是一个虽小、有缺陷但“有效”的示例。它是一个语法树,其中包含特定类型的变量和函数的声明、注释行以及用于替换的占位符声明:

{-# LANGUAGE ExistentialQuantification #-}
module Question
where

import           Control.Applicative
import           Data.Monoid         (Monoid, (<>))
import           Data.String.Utils   (rstrip)

type NumberOfBits = Word
type VariableName = String

data Type = UInt NumberOfBits
          | Int NumberOfBits
          | Void

uint8 = UInt 8
int8 = Int 8

instance Show Type where
    show (UInt w) = "uint" <> …
Run Code Online (Sandbox Code Playgroud)

monads tree haskell abstract-syntax-tree free-monad

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

在 doobie 中为 for-comprehension 编写可选查询?

我想在 doobie 中使用 for-comprehension 在一个事务中运行多个查询。就像是:

def addImage(path:String) : ConnectionIO[Image] = {
  sql"INSERT INTO images(path) VALUES($path)".update.withUniqueGeneratedKeys('id', 'path')
}

def addUser(username: String, imageId: Optional[Int]) : ConnectionIO[User] = {
  sql"INSERT INTO users(username, image_id) VALUES($username, $imageId)".update.withUniqueGeneratedKeys('id', 'username', 'image_id')
}

def createUser(username: String, imagePath: Optional[String]) : Future[User] = {
  val composedIO : ConnectionIO[User] = for {
    optImage <- imagePath.map { p => addImage(p) }
    user <- addUser(username, optImage.map(_.id))
  } yield user

  composedIO.transact(xa).unsafeToFuture
}
Run Code Online (Sandbox Code Playgroud)

我刚开始接触 doobie(和猫),所以我对 FreeMonads 不太熟悉。我一直在尝试不同的解决方案,但为了理解工作,看起来两个块都需要返回一个cats.free.Free[doobie.free.connection.ConnectionOp,?]。

如果这是真的,有没有办法将我的 ConnectionIO[Image](来自 addImage 调用)转换为 cat.free.Free[doobie.free.connection.ConnectionOp,Option[Image]] ?

scala free-monad scala-cats doobie

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