标签: free-monad

Haskell的FreeT和协程类型之间有什么关系

Monad.Reader第19期中的“协程管道”文章中,作者定义了一个泛型Coroutine类型:

newtype Coroutine f m a = Coroutine
  { resume :: m (Either (f (Coroutine f m a)) a)
  }
Run Code Online (Sandbox Code Playgroud)

我注意到这种类型FreeTfree包中的类型非常相似:

data FreeF f a b = Pure a | Free (f b)

newtype FreeT f m a = FreeT
  { runFreeT :: m (FreeF f a (FreeT f m a))
  }
Run Code Online (Sandbox Code Playgroud)

看来FreeTCoroutine是同构的。这是从一个映射到另一个的函数:

freeTToCoroutine
  :: forall f m a. (Functor f, Functor m) => FreeT f m a …
Run Code Online (Sandbox Code Playgroud)

haskell coroutine conduit free-monad haskell-pipes

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

Stackless Scala With Free Monads,完整的例子

以下代码改编自论文(RO Bjarnason,Stackless Scala With Free Monads).

本文的标题总体上指出了所提出的数据结构的目的 - 即在常量堆栈空间中提供递归处理,并让用户以清晰的方式表达递归.

具体来说,我的目标是建立一个monadic结构,在升序时基于恒定堆栈空间中的简单模式匹配,提供不可变树对(二叉树)或列表(n-ary-tree)的结构重写.

sealed trait Free[S[+_], +A]{
  private case class FlatMap[S[+_], A, +B](
    a: Free[S, A],
    f: A => Free[S, B]
  ) extends Free[S, B]

  def map[B](f: A => B): Free[S, B] = this.flatMap((a:A) => Done[S, B](f(a))) 

  def flatMap[B](f: A => Free[S, B]): Free[S, B] = this match { 
    case FlatMap(a, g) => FlatMap(a, (x: Any) => g(x).flatMap(f))
    case x => FlatMap(x, f)
  } 

  @tailrec
  final def resume(implicit S: Functor[S]): Either[S[Free[S, A]], A] …
Run Code Online (Sandbox Code Playgroud)

monads scala stackless free-monad

4
推荐指数
1
解决办法
877
查看次数

在Haskell中,我怎么能在另一个中嵌入一个Free monad呢?

我有两个免费的monad用于不同的上下文中的不同操作.但是,如果特定操作在上下文中,则one(major)DSL需要包含另一个(action):

import Control.Monad.Free

data ActionFunctor next = Wait Timeout next
                        | Read URI next

instance Functor ActionFunctor where
  fmap f (Wait timeout next)  = Wait timeout (f next)
  fmap f (Read uri next)      = Read uri (f next)

type Action = Free ActionFunctor


data MajorFunctor next = Log LogText next
                       | Act Action next
                       | Send Message

instance Functor MajorFunctor where
  fmap f (Log text next)    = Log text (f next)
  fmap f (Act action next) …
Run Code Online (Sandbox Code Playgroud)

monads haskell free-monad

4
推荐指数
2
解决办法
144
查看次数

如何让这个Haskell ADT派生出Show?

ADT是免费的monad:

data Free f r = Free (f (Free f r)) | Pure r
Run Code Online (Sandbox Code Playgroud)

我希望它能够得到它,Show以便我可以在使用它时将其打印出来.例如,如果我有以下内容:

data T next = A next | B next deriving (Show)
aa = Free $ A $ Free $ B $ Pure ()
Run Code Online (Sandbox Code Playgroud)

就像现在一样,如果我添加deriving (Show)FreeADT ,我会收到以下错误:

No instance for (Show (f (Free f r)))
      arising from the first field of ‘Free’ (type ‘f (Free f r)’)
    Possible fix:
      use a standalone 'deriving instance' declaration,
        so you can specify the …
Run Code Online (Sandbox Code Playgroud)

printing haskell show free-monad

3
推荐指数
1
解决办法
157
查看次数

免费Monad的MonadError实例

我用sum数据类型创建了一个非常有用的Free Monad.这抽象了对持久性数据存储的访问:

data DataStoreF next = 
     Create    Asset                           ( String -> next)
  |  Read      String                          ( Asset  -> next)
  |  Update    Asset                           ( Bool   -> next)
  |  UpdateAll [Asset]                         ( Bool   -> next)
  |  Delete    Asset                           ( Bool   -> next)
  |  [...] -- etc. etc.
  |  Error     String

type DataStore = Free DataStoreF
Run Code Online (Sandbox Code Playgroud)

我想将错误消息DataStore的实例MonadError处理为(Free (Error str)):

instance MonadError String DataStore where
  throwError str = errorDS str
  catchError (Free (ErrorDS str)) f = f str …
Run Code Online (Sandbox Code Playgroud)

haskell typeclass overlapping-instances free-monad

3
推荐指数
1
解决办法
198
查看次数

将OOP"装饰器"重构为自由monad结构

我有一些"遗留的"Scala代码(类似Java),它可以进行一些数据访问.有一个装饰器跟踪DAO方法的使用(收集指标),如下所示:

class TrackingDao(tracker: Tracker) extends Dao {
    def fetchById(id: UUID, source: String): Option[String] = {
        tracker.track("fetchById", source) {
            actualFetchLogic(...)
        }
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

我试图把它塑造成一个免费的monad.我为DAO操作定义了以下代数:

sealed trait DBOp[A]
case class FetchById(id: UUID) extends DBOp[Option[String]]
...
Run Code Online (Sandbox Code Playgroud)

我看到两个选择:

a)我可以制作两个解释器DBOp,一个执行实际数据访问,另一个执行跟踪,并将它们组合在一起或者
b)我使跟踪成为一个显式代数,并使用Coproduct在同一个for组合中使用它们或者
c)完全不同的东西!

第一个选项看起来更像是一个"装饰器"方法,它与DBOp第二个选项相关,第二个选项是更通用的解决方案,但需要明确地调用"跟踪"代数.

另外,请注意source原始fetchById呼叫上的参数:它仅用于跟踪.我更愿意从API中删除它.

这是实际问题:如何建模跟踪?

functional-programming scala free-monad scala-cats

3
推荐指数
1
解决办法
192
查看次数

F#异步工作流/任务与免费monad相结合

我正在尝试使用免费的monad模式构建用于消息处理的管道,我的代码看起来像这样:

module PipeMonad =
type PipeInstruction<'msgIn, 'msgOut, 'a> =
    | HandleAsync of 'msgIn * (Async<'msgOut> -> 'a)
    | SendOutAsync of 'msgOut * (Async -> 'a)

let private mapInstruction f = function
    | HandleAsync (x, next) -> HandleAsync (x, next >> f)
    | SendOutAsync (x, next) -> SendOutAsync (x, next >> f)

type PipeProgram<'msgIn, 'msgOut, 'a> =
    | Act of PipeInstruction<'msgIn, 'msgOut, PipeProgram<'msgIn, 'msgOut, 'a>>
    | Stop of 'a

let rec bind f = function
    | Act x -> x |> …
Run Code Online (Sandbox Code Playgroud)

f# asynchronous computation-expression async-await free-monad

3
推荐指数
2
解决办法
393
查看次数

为免费monad定义翻译

purescript-free程序包中,有一个定义此解释器的代码示例:

teletypeN :: forall eff. NaturalTransformation TeletypeF (Eff (console :: CONSOLE | eff))
teletypeN (PutStrLn s a) = const a <$> log s
teletypeN (GetLine k) = pure (k "fake input")
Run Code Online (Sandbox Code Playgroud)

如何定义和运行返回类型为Array Int或的其他解释器State String Int

free-monad purescript

2
推荐指数
1
解决办法
130
查看次数

限制效果,如使用"Freer",使用MTL风格

动机:能够在Free/ Freer-style中控制MTL中的效果.

这个例子可能有点做作 - 想象一个带有一些基本操作的程序(使用GHC 8.2 freer-simple),

#!/usr/bin/env stack
-- stack --resolver lts-10.2 --install-ghc runghc --package freer-simple
{-# LANGUAGE GADTs #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE LambdaCase #-}
import Control.Monad.Freer

data Effect next where
  ReadFilename :: String -> Effect String
  WriteOutput :: Show a => a -> Effect ()
  Computation :: Int -> Int -> Effect Int

readFilename :: Member Effect effs => String -> Eff effs String
readFilename = send …
Run Code Online (Sandbox Code Playgroud)

haskell monad-transformers free-monad

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

在功能域设计中使用 Free Monad

我对函数式编程很陌生。但是,我阅读了有关 Free Monad 的文章,并且正在尝试在玩具项目中使用它。在这个项目中,我对股票的投资组合域进行建模。正如许多书中所建议的那样,我为 定义了 PortfolioService一个代数,为PortfolioRepository.

我想在PortfolioRepository代数和解释器的定义中使用 Free monad 。目前,我没有PortfolioService根据 Free monad 来定义代数。

但是,如果我这样做,在PortfolioService解释器中,PortfolioRepository由于使用的 monad 不同,我无法使用 the 的代数。例如,我不能使用 monads Either[List[String], Portfolio],并且Free[PortfolioRepoF, Portfolio]在同一个for-comprehension 中:(

我怀疑如果我开始使用 Free monad 来模拟代数,那么所有其他需要与它组合的代数都必须根据 Free monad 来定义。

这是真的吗?

我正在使用 Scala 和 Cats 2.2.0。

functional-programming scala free-monad scala-cats

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