Git Product home page Git Product logo

Comments (4)

mageshb avatar mageshb commented on July 25, 2024

Current Alternative instance for Free is giving un-intuitive result.
While interpreting ((getLn *> pure ()) <|> putLn "Actual: This should get printed") , I would expect
putLn to interpreted when there is failure in interpreting getLn. To get the behaviour I want, I had to re-define (<|>) for Free similar to the one above.
Is there a problem in defining Alternative instance for Free in a way that is being done in the following code?

#!/usr/bin/env stack
{- stack
  script
  --resolver nightly-2017-09-07
  --package free
-}
{-# LANGUAGE DeriveFunctor #-}
module Main where

import Control.Monad.Free as FreeM
import Control.Alternative.Free as FreeA
import Control.Applicative


data ActF f
  = GetLine (String -> f)
  | PutLine String f
  deriving (Functor)

type Action a = Free (Alt ActF) a

getLn :: Action String
getLn = liftF $ liftAlt $ GetLine id

putLn :: String -> Action ()
putLn s = liftF $ liftAlt $ PutLine s ()


run p = foldFree foldAlts p

foldAlts as = runAlt interpret as

interpret (PutLine s f) = putStrLn s >> (pure f)
interpret (GetLine f) = ioError $ userError "getline failed"

(<||>) :: (Alternative f) => Free f a ->  Free f a -> Free f a
(<||>) (FreeM.Pure alt1) _              = pure alt1
(<||>) (Free alt1) a2@(FreeM.Pure alt2) = FreeM.Free (alt1 <|> pure a2)
(<||>) (Free alt1) (Free alt2)          = FreeM.Free (alt1 <|> alt2)
infixl 3 <||>

actualCase = ((getLn *> pure ()) <|> putLn "Actual: This should get printed")  
expectedCase = ((getLn *> pure ()) <||> putLn "Expected: This should get printed")


main = do
  run expectedCase
  run actualCase
$./FreeAlt.hs
Expected: This should get printed
FreeAlt.hs: user error (mzero)

from free.

mitchellwrosen avatar mitchellwrosen commented on July 25, 2024

I too wonder if @michaelt's instance is sane. Here's a use-case: "upgrading" the async Concurrently applicative to a monad, while inheriting its concurrent applicative and alternative behaviors.

import Control.Alternative.Free (Alt, liftAlt, runAlt)
import Control.Concurrent.Async (Concurrently(..))
import Control.Monad.Free.Ap -- Not quite, need the alternative Alternative instance

newtype Conc a
  = Conc { unConc :: Free (Alt Concurrently) a }
  deriving (Functor, Applicative, Alternative, Monad)

instance MonadIO Conc where
  liftIO = Conc . liftF . liftAlt . Concurrently

await :: Conc a -> IO a
await = foldFree (runConcurrently . runAlt id) . unConc

For example, this would run f1, then f2, f3 and f4 in parallel, using whichever of f2 and f3 finish first:

foo :: IO Int
foo = 
  await $ do
    i <- f1
    (j, k) <- liftA2 (,) (f2 <|> f3) f4
    pure (i + j + k)

EDIT: Oops, I realized today that this example doesn't need the free Alternative at all. But, it would still benefit from the alternate Alternative instance for Free.

from free.

treeowl avatar treeowl commented on July 25, 2024

The proposed instance, and its extension to FreeT, certainly seem much more useful than the ones currently used for either Free or FreeT. My only major question is whether there's a good way to implement this for Control.Monad.Trans.Free.Church. Also, whether there's a good way to implement this for other "final" free monad transformer definitions like

type f ~> g = forall x. f x -> g x

newtype FF f m a = FF
  { runFF :: forall n. Monad n
      => (f ~> n) -- Any natural transformation
      -> (m ~> n) -- A monad morphism
      -> n a }

Maybe one of you wizards can find good approaches.

from free.

treeowl avatar treeowl commented on July 25, 2024

Note to email followers: my last comment has been edited.

from free.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.