how would I do this properly in Haskell?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

how would I do this properly in Haskell?

Dennis Raddle
I have a problem which I can solve with OO organization, but I want to know how to do it properly in Haskell.

I have a search optimization problem in which there are a lot of individual fitness functions which combine scores to give an overall fitness level.

Each fitness function will be associated with data, both initial data to configure it, and a cache that it maintains.

So I could have something like this:

data Fitness = Fit1 SomeData1
             | Fit2 SomeData2
             | Fit3 SomeData3

-- this function would evaluate the fitness of a particular
-- result of type 'S' (in my case, a partially-constructed
-- musical composition)
evaluate :: Fitness -> S -> (Fitness,Double)

-- something like this would have to be written for
-- every sub-type of "Fitness"
evaluate (Fit1 d) s = (Fit1 d',v)
  where
    (d',v) = evaluate1 d s

evaluate1 :: SomeData1 -> S -> (SomeData1,Double)


Is there a better way to do this?

D


                   

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: how would I do this properly in Haskell?

John Wiegley-2
>>>>> "DR" == Dennis Raddle <[hidden email]> writes:

DR> I have a search optimization problem in which there are a lot of
DR> individual fitness functions which combine scores to give an overall
DR> fitness level.

DR> Each fitness function will be associated with data, both initial data to
DR> configure it, and a cache that it maintains.

This sounds a lot like a network of Moore machines, which could be combined
monoidally to arrive at the final fitness function.

--
John Wiegley                  GPG fingerprint = 4710 CF98 AF9B 327B B80F
http://newartisans.com                          60E1 46C4 BD1A 7AC1 4BA2
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: how would I do this properly in Haskell?

Dennis Raddle
I'm an advanced beginner, and I'm finding it hard to comprehend Data.Machine.Moore. Is there a way to explain more to me how this would look in practice? Or is there another way to organize it that is less "computer-sciency" and I could work with more easily?

D

On Thu, Aug 24, 2017 at 9:13 PM, John Wiegley <[hidden email]> wrote:
>>>>> "DR" == Dennis Raddle <[hidden email]> writes:

DR> I have a search optimization problem in which there are a lot of
DR> individual fitness functions which combine scores to give an overall
DR> fitness level.

DR> Each fitness function will be associated with data, both initial data to
DR> configure it, and a cache that it maintains.

This sounds a lot like a network of Moore machines, which could be combined
monoidally to arrive at the final fitness function.

--
John Wiegley                  GPG fingerprint = 4710 CF98 AF9B 327B B80F
http://newartisans.com                          60E1 46C4 BD1A 7AC1 4BA2


_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: how would I do this properly in Haskell?

John Wiegley-2
>>>>> "DR" == Dennis Raddle <[hidden email]> writes:

DR> I'm an advanced beginner, and I'm finding it hard to comprehend
DR> Data.Machine.Moore. Is there a way to explain more to me how this would
DR> look in practice? Or is there another way to organize it that is less
DR> "computer-sciency" and I could work with more easily?

Thinks of a Moore machine as a packaged up State function, where you have an
initial state, and the type of that state is hidden within the machine.  For
example:

    {-# LANGUAGE ExistentialQuantification #-}
   
    data Moore i m o = forall s. Moore
        { mooreInit :: s
        , mooreFunc :: i -> StateT s m o
        }

This machine is really just a packaged function, yielding outputs from inputs,
while dependent on an internal state that may vary at each call.

Since the state is "existential" (or private to Moore), it can be changed
freely when you combine machines:

    instance (Monad m, Monoid o) => Monoid (Moore i m o) where
        mempty = Moore () (const (return mempty))
        Moore s1 f1 `mappend` Moore s2 f2 = Moore (s1, s2) go
          where
            go ev = StateT $ \(st1, st2) -> do
                (mres, st1')  <- runStateT (f1 ev) st1
                (mres', st2') <- runStateT (f2 ev) st2
                return (mres <> mres', (st1', st2'))

Something like this could serve your needs, without needing an external
package like 'machines'. I've used it to do almost just what you described
initially.

--
John Wiegley                  GPG fingerprint = 4710 CF98 AF9B 327B B80F
http://newartisans.com                          60E1 46C4 BD1A 7AC1 4BA2
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: how would I do this properly in Haskell?

Dennis Raddle
Thanks very much! I'll look at it in detail.

D

On Thu, Aug 24, 2017 at 10:30 PM, John Wiegley <[hidden email]> wrote:
>>>>> "DR" == Dennis Raddle <[hidden email]> writes:

DR> I'm an advanced beginner, and I'm finding it hard to comprehend
DR> Data.Machine.Moore. Is there a way to explain more to me how this would
DR> look in practice? Or is there another way to organize it that is less
DR> "computer-sciency" and I could work with more easily?

Thinks of a Moore machine as a packaged up State function, where you have an
initial state, and the type of that state is hidden within the machine.  For
example:

    {-# LANGUAGE ExistentialQuantification #-}

    data Moore i m o = forall s. Moore
        { mooreInit :: s
        , mooreFunc :: i -> StateT s m o
        }

This machine is really just a packaged function, yielding outputs from inputs,
while dependent on an internal state that may vary at each call.

Since the state is "existential" (or private to Moore), it can be changed
freely when you combine machines:

    instance (Monad m, Monoid o) => Monoid (Moore i m o) where
        mempty = Moore () (const (return mempty))
        Moore s1 f1 `mappend` Moore s2 f2 = Moore (s1, s2) go
          where
            go ev = StateT $ \(st1, st2) -> do
                (mres, st1')  <- runStateT (f1 ev) st1
                (mres', st2') <- runStateT (f2 ev) st2
                return (mres <> mres', (st1', st2'))

Something like this could serve your needs, without needing an external
package like 'machines'. I've used it to do almost just what you described
initially.

--
John Wiegley                  GPG fingerprint = 4710 CF98 AF9B 327B B80F
http://newartisans.com                          60E1 46C4 BD1A 7AC1 4BA2


_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.