Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
loose-fish
Apr 1, 2005
While playing around with generic execution models I ran into the following, a typeclass with a function that returns another instance of that typeclass:
code:
class Processor a where
    process :: Processor b => a -> Int -> b

data P = P Int

instance Processor P where
    process (P x) y = P y
-- can't return P because it's no Processor

-- more precise, but pointless
instance (Processor P) => Processor P where
    process (P x) y = P y
Is there a way to achieve something like this in Haskell? Type families maybe? I'm not up to speed on all extensions...

Adbot
ADBOT LOVES YOU

loose-fish
Apr 1, 2005
Thanks for clearing that up! I had a fundamental misconception of type classes, guess the 'forall' should've tipped me off...

I'm trying to find a solution for processors with arbitrary local state, and a function to apply an event to the global state according to the current processor. (I say 'State' but I don't care if it's in the State Monad, it's just what I'm using here).
This is the best I've come up with so far:
code:
import Control.Monad.State (State, put)

type Model = String
type Event = Int

data AppState = AppState { _model :: Model
                         , _processor :: Event -> State AppState ()
                         }

class Processor a where
    process :: a -> Event -> State AppState ()


data P = P Int

instance Processor P where
    process (P 0) x = put $ AppState "foo" (process $ Q x (x * 2))  -- change processor to Q
    process (P _) x = put $ AppState (show x) (process $ P x)


data Q = Q Int Int

instance Processor Q where
    process (Q 0 0) x = put $ AppState "bar" (process $ P x)  -- change processor to P
    process (Q _ _) x = put $ AppState (show x) (process $ Q x (x * 2))
I know the simple way to do it would be something like this:
code:
data Processor = P Int | Q Int Int

process :: Processor  Model -> Event -> (Processor, Model)
process (P p) m = processP p m
process (Q q) m = processQ q m
But this would make it impossible to add new Processors in separate modules...

  • Locked thread