You are viewing yumagene

Everyone has been exposed to liftM and it's offshoots liftM2 and liftM3, which extend lifting to multi-parameter lifts. I have developed some new {can't find with hoogle anyway} lifting functions for monadic operations, that apply a function at depth into multi layered monads.

Will begin with one that goes to a monad contained in one other monad and both of those inside another enclosing monad.. so three levels deep.

lift3M
:: forall a1 r (m1 :: * -> *) (m11 :: * -> *) (m :: * -> *).
(Monad m, Monad m11, Monad m1) =>
(a1 -> r) -> m1 (m11 (m a1)) -> m1 (m11 (m r))

Two example using a list of lists of Maybe values:

lift3M (* 4) [[Nothing,Just 2,Just 5],
[Nothing],
[Just 34,Nothing,Just 19]
]

[[Nothing,Just 8,Just 20],
[Nothing],
[Just 136,Nothing,Just 76]]

This is just a the same as above but more practical in that
it concats the results doubly and eliminates the Maybe
leaving a list of the numeric results from the raw computation
above {uses arrow notation}:

lift3M (* 4) >>> concat >>> catMaybes $
[[Nothing,Just 2,Just 5],
[Nothing],
[Just 34,Nothing,Just 19]]

[8,20,136,76] <- distilled results!

This is just an example of lift2M to lift4M series of functions.

Hope that is interesting to someone out there! -- gene

Unlocking the IO Monad Secrets.

Okay... you getLine ... not in a 'DO construct". Resulting in a IO String value.. and then what?


Well we build some new functions from existing ones of type "String-> IO ()" and put
the BIND into the new definition so we can change them to IO String -> IO (). And the
obvious first one is PutStrLn to PutStrLnIO. Now you can as an alternate to the (>>=) or (=<<)
that use here, use liftM. And I suppose that is the prefered by many "right" way to state the
situation.. as that is what I am doing .. but


Function putStrLnIO:
This function takes an IO String and prints it
to the console with a newline appended.


>putStrLnIO :: IO String -> IO ()
>putStrLnIO = ( putStrLn =<<)

==============================
Function getLineApp:
The function reads a line from the console and
performs the (String -> String) function on that
line and outputs the string with those modifications
as an (IO String).



>getLineApp :: (String -> String) -> IO String
>getLineApp f = (f >>> return) =<< getLine


Type of partially applied function getLineApp:

*> :t (getLineApp (++ "ing"))
(getLineApp (++ "ing")) :: IO String

-------------------------
EXAMPLE OF USAGE:

*> getLineApp (++ "ing")
cement
"cementing"


==============================

Function getAppPutLn:
This function gets a line from the console, applies the
supplied (String -> String) function and puts the result
to the console with a newline appended. It is just a putting
combinatorial formed by building a higher order function from
the previously defined building blocks putStrLnIO with getLineApp
to form the new function.

>getAppPutLn :: (String -> String) -> IO ()
>getAppPutLn f = putStrLnIO (getLineApp f)

-------------------------------
EXAMPLES OF USAGE:

*> getAppPutLn (++ "ed")
pick
picked

More complex function applied in this example, but
the basics are still simply a function to get a string value
and apply a function to it. In this case we are not using it in
the raw, but in a new function definition.

>talk n = sequence_ $
> take n $
> repeat (getAppPutLn (((++) "This is ") >>>
> (++ "ing") >>>
> (++ " extremely nicely")))

-----
Example run of that definition:

*>talk 3
help
This is helping extremely nicely
sleep
This is sleeping extremely nicely
draw
This is drawing extremely nicely

---------------------------

*> getAppPutLn (read >>> (* 5) >>> show)
12 <-- user typed string entered at console.
60

Same idea as that one, but added some sequencing to allow it to do three iterations
and then quit. It converts as did the last example from String -> Integer with the 'read'
and then takes the square of that and then converts it back to a String for output with 'show'
all in that one arrowized function (read >>> (* 5) >>> show) supplied as the sole
parameter to getAppPutLn.

*Big3> sequence_ $ take 3 $ repeat (getAppPutLn (read >>> (^ 2) >>> show))
3 <-- user typed string entered at console.
9
5 <-- user typed string entered at console.
25
7 <-- user typed string entered at console.
49

Okay so no rocket science here.. just some very simple one line definitions.. and that is exactly
the point that I wanted to bring forth here.. Those "IO Monad Secrets" are not that tough a nut
to crack. This has I suppose been truly very obvious to others, but it took me a bit of mucking
about to unlock for my own use the secrets of what I call the Big3... Monads, Idioms {applicative functors},
and arrows. Now I still need to unlock for myself all the variants of say arrows, such as ArrowLoop and
many other wonderful constructs.. But none of it need be scary, and I am sure that once cracked or unlocked
will be no more Hairy or Scary then these first run revelations.

Hope this is helpful to someone else, and may speed their understanding of at least this much of things, but
if not, well maybe the way the next guy puts it will spring the mind trap. I found that just by being persistent
and reading things that I had no idea what I was really reading at times.. but not giving up, that I can do some
pretty neat things now with these various computation encapsulators.

happy day {or night} to y'all,
gene
Here is a little operator that just puts the mapM_ cart before horse. Didn't need to build this really
but, I unlike others, do like to operate with operators. I find if i use any operator more then about
20 times, that it becomes as natural as saying |-> as it does mapM_.

(|->) ::
forall a (m :: * -> *) b. (Monad m) =>
(a -> m b) -> [a] -> m ()
(|->) function = mapM_ function

putStrLn |-> words "Fight the good fight."
Fight
the
good
fight.

Now keep in mind that I could have just made another function that encapsulated the
putStrLn function in it, maybe putStrLnMap_ but then the generic nature of the operator
would be lost. It would be used just as easily with a function that writes a structure to a file
as to the console.

======================================

Here is again an arrow that has a monad up front that is encapsulated in it, then a function
(which by definition is an arrow, though good practice I suppose is to put the 'arr' in front of it,
and then an applicative operator '<$> is used in the next part of the arrow, and all followed with
the (putStrlLn |->) invocation to do the line by line output of the un-monaded and flattened data.


(>>= (join >>> return)) >>> fromJust >>> (show <$>) >>> (putStrLn |->) $ (Just [[3,4,5],[2,5,6]])
3
4
5
2
5
6
========================================
In trying to get a handle on monads, which I was having more then a bit of trouble with for some time, I got so disgusted that I decided to look at the arrow notation, and at least I was able to make use of them, and then I took a look at applicative functors, and the various operators. In doing what I call investigative programming, "playing around with" could be a better way to put it, I came to find that all three could be mixed and matched to make a better soup then just one paradigm alone in some cases. If another person wants to try this, the main thing to remember is that in order to do that each computational unit, HAS to be encapsulated, usually just by a set of parenthesis to keep things in order, or things will blow up with some sort of compiler error message about mismatch, or precedence problems.. but all that can be avoided by a simple surrounding of whichever, arrow, applicative Functor or monad, in use with said parenthesis.
I think that some examples will make this much clearer. So I will use a run of the ghci with a ghc extras turned on for --farrows and --ghc-exts and then I fire up a mostly empty module called Big3.lhs that just has the imports of Control.Arrow, Control.Applicative, and Control.Monad, to allow all three of those notations.

Standard monadic bind:

*Big3> [[2,4,6],[7..13],[10,20..50]] >>= return . fmap (* 3)
[[6,12,18],[21,24,27,30,33,36,39],[30,60,90,120,150]]

and the same although w/o the return, so leaves unwrapped:

*Big3> [[2,4,6],[7..13],[10,20..50]] >>= fmap (* 3)
[6,12,18,21,24,27,30,33,36,39,30,60,90,120,150]

Now here is the result I was talking about with the mixed usage and a failure to compute due to a not having the individual types of computations enclosed properly. So when I see this type of error message, I immediately know that I have forgotten to slap some parenthesis around some part of the computation to isolate it properly.
-----
*Big3> [[2,4,6],[7..13],[10,20..100]] >>= ((* 3) <$>) >>> return

:1:0:
Precedence parsing error
cannot mix `>>=' [infixl 1] and `>>>' [infixr 1] in the same infix expression
-----
now here is all that is needed to fix that problem as the improper mixing is between the monad bind { >>= } and the arrow { >>> } operators. The applicative { <$> } is already enclosed or it would ring bells with both the >>= and the >>>. So here is the fix:

-------
*Big3> [[2,4,6],[7..13],[10,20..100]] >>= (((* 3) <$>) >>> return)
[[6,12,18],[21,24,27,30,33,36,39],[30,60,90,120,150,180,210,240,270,300]]
-------
NOTICE that this is the same as the { return . fmap (* 3) } above.. just using all three notations.. I never said that it will always be a less obsfucated choice.. but sometimes it is a much better choice. The real point is that you do have the choice. Now that should serve to show everything a person would need to see that they can be mixed.. but more is at hand. This is and applicative functor operation " (^ 2) <$> " being applied to a list value generated by an enclosed monad, " ([1..10] >>= return . (* 5)) ".
----
*Big3> (^ 2) <$> ([1..10] >>= return . (* 5))
[25,100,225,400,625,900,1225,1600,2025,2500]
-----
Now a better way in my opinion to skin that cat is to skip the monadic element and use an arrow computational element composed of the (* 5) and the (^ 2) directly applied to the initial list [1..10].
------
*Big3> ((* 5) >>> (^ 2)) <$> [1..10]
[25,100,225,400,625,900,1225,1600,2025,2500]
------
This keeps all the computational elements grouped together and is more easily read, and due to the use of the >>> the computations are written in a more natural to me anyway left to right progress of the various functions being applied. If you are really enamored by the right to left of the (.) , composition notations, well you can always use a series of the arrow operators (<<<) that accomplish that.
Okay here is the true motivation to using arrows ... as the notation for splitting into two branches and doing separate computations on both sides is not as clean in much of any other type of notation. In this case a list of the pairs consisting of the "id" of the element being operated on from the original list, and the result of the computation.
-------
*Big3> (id &&& ((* 5) >>> (^ 2))) <$> [1..5]
[(1,25),(2,100),(3,225),(4,400),(5,625)]
-------
And then the slightly more complex version that puts the results one per line:
-------
*Big3> (((id &&& ((* 5) >>> (^ 2)))) <$>) >>> (show <$>) >>> mapM_ putStrLn $ [1..7]
(1,25)
(2,100)
(3,225)
(4,400)
(5,625)
(6,900)
(7,1225)

Okay this may not seem too worthwhile to this point, as we are just doing things to the LIST Monad.. aka the also LIST Functor.
ah yes it is.. and so is the Maybe monad a Functor too.. which leads to a much more wonderful use of the applicatives, as they
don't care too much about the type of functor that they are dealing with..
Here is some more motivation in the dressing of a new operator that (<$$>) which bores down a through two layers of functor to apply a function to the innards of the second one down. Here is the type signature of it:
*Big3> :t (<$$>)
(<$$>)
:: forall a b (f1 :: * -> *) (f :: * -> *).
(Functor f, Functor f1) =>
(a -> b) -> f1 (f a) -> f1 (f b)
so that (a to b) function is applied to the elements of the inner functor {f} which is enclosed in the outer functor {f1}. So for the first set of examples I will use a Maybe (Maybe a):
----
*Big3> (* 4) <$$> Just Nothing
Just Nothing
*Big3> (* 4) <$$> Just (Just 5)
Just (Just 20)
-------

Okay not too impressive, but it does what it advertises ----
Now a bit more interesting, a list of Maybe (Num) that is applied to by an arrow computation.
------
( ---- arrow ---- ) (app) (----List of Maybe Num -------------- )
*Big3> ((+ 3) >>> (* 10)) <$$> [Nothing,Just 3,Just 7,Nothing,Just 9]
[Nothing,Just 60,Just 100,Nothing,Just 120]

This can be prettied up by pulling discarding the Nothings and giving the resulting "a" value of the "Just a"s using catMaybe.

*Big3> (((+ 3) >>> (* 10)) <$$>)
>>> Maybe.catMaybes
$ [Nothing,Just 3,Just 7,Nothing,Just 9]

[60,100,120]

Also have a few more applicative operators that I have conjured up that let me go down to level 3 and 4 and are:

(<$$$>)
:: forall a
b
(f2 :: * -> *)
(f1 :: * -> *)
(f :: * -> *).
(Functor f, Functor f1, Functor f2) =>
(a -> b) -> f2 (f1 (f a)) -> f2 (f1 (f b))

eg:
*Big3> (* 3) <$$$> [[Just 3,Nothing,Just 4],[Nothing],[Just 5,Just 6,Nothing]]
[[Just 9,Nothing,Just 12],[Nothing],[Just 15,Just 18,Nothing]]

This one is a bit dense..but ..will spread it out down page to try and make it easier to read:
*Big3> Maybe.catMaybes $
((
(words <$>) >>>
((\cs -> if length cs < 3 then Nothing else Just cs)<$$>))
) ["follow is a test","As is offer bloat"] >>=
( (++ "ing") <$$>)
["following","testing","offering","bloating"]

This one just goes down another level into a fourth layer of functor, and BELIEVE it or NOT, I have used it too.
These can occur in situations of a lookup of a lookup of a perhaps lookup where you could have a result like:
[Nothing, Just Nothing, Just [Just a,Nothing,Just c]]

(<$$$$>)
:: forall a
b
(f3 :: * -> *)
(f2 :: * -> *)
(f1 :: * -> *)
(f :: * -> *).
(Functor f, Functor f1, Functor f2, Functor f3) =>
(a -> b) -> f3 (f2 (f1 (f a))) -> f3 (f2 (f1 (f b)))

--------- That's all for now.. probably more than enough!!

Doing things the hard way AND using Arrows.

DOING THINGS THE HARD WAY!! In doing some messing about with arrows, and building some arrow-matic tools, I used an example that while it was elegant and somewhat complex, well, it was complex to no purpose, other than to show an example use of the newly formed arrow building function: arrow2
Well I do guess I ought to put that forth first,the module GenArrow, after about 2 hours of work the other day. Pretty preliminary, but enough to show where I am exploring at the moment. Just trying some arrow development using the ghc extensions for arrows which can be used with the ghc compiler or the interpreter ghci using the -farrows as a parameter when firing up either one. The -farrows allows the arrow "do" notation, taken from the syntactic candy of monadic fame.
================================================
Module: GenArrow
Author: Eugene Arthur
Date Started: 2008/01/23
Last Updated: 2008/01/23

Purpose: A first diddling around with Arrows... just to do a
proof of concept on their use. Seems that they could
be wildly useful, but will know more later.


Copyright (C) 2008 Eugene Arthur
mailto:Gene<yumagene@gmail.com>

This program is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation;
Version 3 of the License.

This program is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more
details. You should have received a copy of the GNU General
Public License along with this program; if not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth
Floor, Boston, MA 02110-1301 USA.

>module GenArrow (
> arrow2,
> arrow3,)
> where

>import Control.Arrow



=============================================
Function arrow2: This function builds a higher order
function building function that
applies two supplied functions to
a value, giving two intermediate values
that are then combined using the application
of a third supplied function called op1 the
definition.

>arrow2 ::
> forall t t1 (t2 :: * -> * -> *) t3 b.
> (Control.Arrow.Arrow t2) =>
> t2 t t1 -> t2 t t3 -> (t3 -> t1 -> b) -> t2 t b

>arrow2 f1 f2 op1 = proc x -> do
> fx1 <- f1 -< x
> fx2 <- f2 -< x
> returnA -< (op1 fx2 fx1)

-------------
USAGE:
This execution using: "ghci -fglasgow-exts -farrows GenArrow"

*GenArrow> let resultPair f = arrow2 id f (\y x -> (,) x y )
*GenArrow> resultPair (*5) 4
(4,20)

*GenArrow> map (resultPair (^2)) [2..8]
[(2,4),(3,9),(4,16),(5,25),(6,36),(7,49),(8,64)]

now of course... this is not a good example as resultPair can be
constructed without using arrows and with a lot less obscurity as:
* resultPair f x = (x,(f x))
and works just the same and everything.. only need the arrowized version for demonstration purposes.. so don't really have a good example yet of when arrow2 would be useful, but this example is not one of those cases!!

============================================
function resultPair: This function as defined above as an
example has some value in showing the
original data and the results of
the application of a function.

>resultPair f = arrow2 id f (\y x -> (,) x y )

============================================
function mapResultPair: This function just combines the mapping
with the generation of the (x,f x)

>mapResultPair f = (map (resultPair f))

ghci> mapResultPair (\(x,y) -> sqrt ((x ** 2) + (y ** 2))) [(3,4),(2,7),(6,9)]
result:
[((3.0,4.0),5.0),
((2.0,7.0),7.280109889280518),
((6.0,9.0),10.816653826391969)]



=============================================
Function arrow3: This function builds a higher order
function building function that
applies three supplied functions to
a value, giving three intermediate
values that are then combined using
the application of two more functions
(called op1 and op2 in the definition)
arrow3 :: forall t t1 (t2 :: * -> * -> *) t3 t4 b t5.
> (Control.Arrow.Arrow t2) =>
> t2 t t1
> -> t2 t t3
> -> t2 t t4
> -> (t3 -> t1 -> t5)
> -> (t4 -> t5 -> b)
> -> t2 t b

>arrow3 f1 f2 f3 op1 op2 = proc x -> do
> fx1 <- f1 -< x
> fx2 <- f2 -< x
> fx3 <- f3 -< x
> returnA -< (op2 fx3 (op1 fx2 fx1))

-------------
USAGE:
This execution using: "ghci -fglasgow-exts -farrows GenArrow"
{in the functions below the parameters are put on separate lines for clarity and of course cannot be done in ghci.}

*GenArrow> let testF = arrow3
(\x -> x + 3)
(\x -> x * 7)
(\x -> x ^ 2)
(*) (+)

*GenArrow> testF 3
135

============ end of module GenArrow ============

THE HARDER WAY:

Now the bit about the harder way.. well everything that was used as an example of use of the functions defined above could be done in a purely functional way with no use of monads or arrows.

For instance a function such as the resultF function used in the arrow3 USAGE section of the module above, could be as noted above, but I will include here again with a different name here:

ghci> pairF f (a,b) = (f a,f b)

ghci>map (pairF (< 8)) [(1,5),(12,3),(8,9),(8,8),(9,4)]
result:
[(True,True),(False,True),(False,False),
(False,False),(False,True)]

Hopefully I can find a way to use the arrow2 and arrow3 functions that make a bit more sense.. Actually they probably are just a reinvention of one of the (>>>) or (&&&) or some other function/operator already in the arrow class. I will have to look more closely at the type sigs of those to discover a bit more on that. No time right now to do that. Let me know back if any of these functions are useful or if you see any errors or such. This was just a fun learning exercise on my part.

-- gene
Module: mapP
Author: Eugene Arthur
Started: Wednesday, September 6, 2006
Last Updated: Thursday, September 7, 2006

Purpose: Production of a mapping function that returns a list
consisting of pairs containing the originating argument
and the result of the application of the function to that
argument. These functions were built and tested using
the Glasgow Haskell Compiler version 6.4.2 and
specifically: ghci -fglasgow-exts


Copyright (C) 2006 Eugene Arthur mailto:Gene<yumagene@gmail.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.


>module MapP (mapP,putMapP) where


============= Paired Results From Map =================================
This is just a wrapper around map to return as the result of the application
of the function 'f' to a list of 'a' a list consisting of the original value
'a' and the result of the mapping (f a).

============= mapP .. the actual mapping function ======

------ This is the mapping function that merely maps the curried function
resultP initialized with function 'f' over the list xs, returning
the result as a list of pairs of the initial values and values
obtained by the function application.


>mapP :: forall a b. (a -> b) -> [a] -> [(a, b)]
>mapP f xs = map (resultP f) xs
> where
> resultP f a = (a,(f a))

Example of Usage:

*MapP> mapP (+100) [1..10]

[(1,101),(2,102),(3,103),(4,104),(5,105),(6,106),(7,107),(8,108),(9,109),(10,110)]

-------

*MapP> reverse [5,10..60] >>= (mapP (sqrt.(+3))).return

[(60.0,7.937253933193772),(55.0,7.615773105863909),(50.0,7.280109889280518),
(45.0,6.928203230275509),(40.0,6.557438524302),(35.0,6.164414002968976),
(30.0,5.744562646538029),(25.0,5.291502622129181),(20.0,4.795831523312719),
(15.0,4.242640687119285),(10.0,3.605551275463989),(5.0,2.8284271247461903)]

--------

putStrLn $
words "walk talk climb ski stuff lean stand lay" >>=
(mapP (++"ing")).return >>=
((map (++"\n")).(map show)).return >>=
(foldr (++) "\n").return

("walk","walking")

("talk","talking")

("climb","climbing")

("ski","skiing")

("stuff","stuffing")

("lean","leaning")

("stand","standing")

("lay","laying")



========= prnMapP post helper function =================

----- this function just prints one result from the generated list
----- of results from the application of mapP, one per line..

>putMapP :: forall a b. Show (a, b) => (a -> b) -> [a] -> IO ()
>putMapP f xs = putStr $ foldl (++) "\n" $ map (++"\n") $ map show $ mapP f xs

Example of Usage:

*MapP> putMapP ((*3).(+2)) [10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170,180,190,200]

(10,36)
(20,66)
(30,96)
(40,126)
(50,156)
(60,186)
(70,216)
(80,246)
(90,276)
(100,306)
(110,336)
(120,366)
(130,396)
(140,426)
(150,456)
(160,486)
(170,516)
(180,546)
(190,576)
(200,606)

*MapP> putMapP (\x -> ((sqrt x),(x^3))) [1..12]

(1.0,(1.0,1.0))
(2.0,(1.4142135623730951,8.0))
(3.0,(1.7320508075688772,27.0))
(4.0,(2.0,64.0))
(5.0,(2.23606797749979,125.0))
(6.0,(2.449489742783178,216.0))
(7.0,(2.6457513110645907,343.0))
(8.0,(2.8284271247461903,512.0))
(9.0,(3.0,729.0))
(10.0,(3.1622776601683795,1000.0))
(11.0,(3.3166247903554,1331.0))
(12.0,(3.4641016151377544,1728.0))


==========================================================================
Module: PairsLogic
Author: Eugene Arthur
Date Started: 2007/04/23
Last Updated: 2007/04/23

Purpose:

The following functions all perform boolean tests on pairs and apply either
AND or OR to the result of the tests. The parameters for all the functions
are:

andor -- replaced by either: (&&) or (||) note: must be inclosed in
parenthesis.

testFst -- the boolean test to apply to the first element in the pair
testSnd -- the boolean test to apply to the first element in the pair
eg for both: (<5), (=="Female"), (=>"A"), etc.

p -- is the pair to be tested,
ps -- in the case of the mapping functions where ps denotes a list
of pairs, which of course could be an empty list or a list
containing only one pair, or many thousands of pairs.

----------------------------------------------------------------------

Copyright (C) 2007 Eugene Arthur mailto:Gene<yumagene@gmail.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; Version 2 of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

>module PairsLogic where

>import MapP




======= Function: pairTest ==========
This function is for use in applying separate boolean tests
on each of the elements of the pair, and either returning the
ORed or ANDed result of those tests.

>pairTest ::
> forall a b t t1 t2.
> (t -> t1 -> t2) -> (a -> t) -> (b -> t1) -> (a, b) -> t2

>pairTest andor testFst testSnd p = andor (testFst (fst p)) (testSnd (snd p))


Usage:

In the following test the ANDed result of testing of (=="horse) to
the first element in the pair, which is "pig" {False} and the test to
determine if the 3 in the second part of the pair is less than 5 {True}
results in False as the first test was False and so the AND returned
False.

*PairsLogic> pairTest (&&) (=="horse") (<5) ("pig",3)
False

The next test is exactly the same as the ANDed one above, but the
AND ie: (&&) is replaced with an OR (||) so because (3 < 5) in the
test for the second element returns True, the OR is satisfied, and
returns True as the result

*PairsLogic> pairTest (||) (=="horse") (<5) ("pig",3)
True


======= Function: mapPairTest ======================
This function is just the mapping of pairTest over a list
of pairs returning a list of the boolean results, one result
for each pair in the list.

>mapPairTest ::
> forall t t1 t2 a b.
> (t -> t1 -> t2) -> (a -> t) -> (b -> t1) -> [(a, b)] -> [t2]

>mapPairTest andor testFst testSnd ps = map (pairTest andor testFst testSnd) ps


Usage:
*PairsLogic> mapPairTest (&&) (=="horse") (<5) [(animal,age) |animal <- ["cow","horse","pig"],age <- [1..8]]
[False,False,False,False,False,False,False,False,True,True,True,True,False,
False,False,False,False,False,False,False,False,False,False,False]


======= Function: mapPairTestWpairs ===============
This function maps the parameters as in mapPairTest, the only difference
being that the result returns a pair consisting of the original pair and
the boolean result of the ORing or ANDing of the tests.


>mapPairTestWpairs ::
> forall t t1 t2 a b.
> (t -> t1 -> t2)
> -> (a -> t)
> -> (b -> t1)
> -> [(a, b)]
> -> [((a, b), t2)]

>mapPairTestWpairs andor testFst testSnd ps = mapP (pairTest andor testFst testSnd) ps

Usage:
*PairsLogic> mapPairTestWpairs (&&) (=="horse") (<5) [(animal,age) |animal <- ["cow","horse","pig"],age <- [1..8]]
[(("cow",1),False),(("cow",2),False),(("cow",3),False),(("cow",4),False),(("cow",5),False),(("cow",6),False),
(("cow",7),False),(("cow",8),False),(("horse",1),True),(("horse",2),True),(("horse",3),True),
(("horse",4),True),(("horse",5),False),(("horse",6),False),(("horse",7),False),(("horse",8),False),(("pig",1),False),(("pig",2),False),(("pig",3),False),(("pig",4),False),(("pig",5),False),(("pig",6),False),(("pig",7),False),(("pig",8),False)]

*PairsLogic> mapPairTestWpairs (||) (=="horse") (<5) [(animal,age) |animal <- ["cow","horse","pig"],age <- [1..8]]
[(("cow",1),True),(("cow",2),True),(("cow",3),True),(("cow",4),True),(("cow",5),False),(("cow",6),False),
(("cow",7),False),(("cow",8),False),(("horse",1),True),(("horse",2),True),(("horse",3),True),
(("horse",4),True),(("horse",5),True),(("horse",6),True),(("horse",7),True),(("horse",8),True),(("pig",1),True),(("pig",2),True),(("pig",3),True),(("pig",4),True),(("pig",5),False),(("pig",6),False),(("pig",7),False),(("pig",8),False)]



======== Function putMapPairTestWpairs =============
This function maps the parameters as in mapPairTest, the only difference
being that the result returns a pair consisting of the original pair and
the boolean result of the ORing or ANDing of the tests as in
function mapPairTestWpairs, but adds the output of the results one per
line. as the output is consumed as (IO),in a putStrLn,the results
cannot used by another function. The formatting makes it much easier to
see results, but if there are many result since it is used for console
output, the results will if too numerous, scroll off the screen. Still
handy for seeing results if the data set is small enough.





>putMapPairTestWpairs ::
> forall t t1 t2 a b.
> (Show ((a, b), t2)) =>
> (t -> t1 -> t2) -> (a -> t) -> (b -> t1) -> [(a, b)] -> IO ()

>putMapPairTestWpairs andor testFst testSnd ps = putMapP (pairTest andor testFst testSnd) ps

Usage:

*PairsLogic> putMapPairTestWpairs (||) (=="horse") (<3) [(animal,age) |animal <- ["cow","horse","pig"],age <- [1..4]]

(("cow",1),True)
(("cow",2),True)
(("cow",3),False)
(("cow",4),False)
(("horse",1),True)
(("horse",2),True)
(("horse",3),True)
(("horse",4),True)
(("pig",1),True)
(("pig",2),True)
(("pig",3),False)
(("pig",4),False)
Author : Gene Arthur
Start Date : 2006-06-25
Last Update : 2006-06-27

Purpose: The TriPoly module is designed to take arbitrarily
complex formulas in three variables and return the
result for a given x, y, and z. All values are Double
floating point, including the exponents to x,y and z.
They are forced to that by the use of (**) rather than
(^), and that could be changed, or new Integer only
functions written with that being the only change, for
speed or precision, but that was a judgement call on my
part for ultimate flexibility of use out of the box.

All examples were derived and tested using the GHC 6.6
interpeter with extensions onboard:
ghci -fglasgow-exts TriPoly

Copyright (C) 2006 Eugene Arthur

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.


>module TriPoly where

========================================

>triPoly :: forall b. Floating b => (b, (b, b), (b, b), (b, b)) -> b

>triPoly (a,(x,xe),(y,ye),(z,ze)) = product [a,x**xe,y**ye,z**ze]

========================================

>triPolyMap :: [(Double,
> (Double, Double),
> (Double, Double),
> (Double, Double))]
> -> [Double]


>triPolyMap = (map triPoly)


------------ USAGE ------------

This example returns the two element list of the results of
solving the two equations.

*TriPoly> triPolyMap [(2,(23,3),(12,1),(0,0)),
(13,(12,2),(7,3),(5,3))]

[292008.0,8.0262e7]

--------
This example takes the average of two formulas in x,y,z.

*TriPoly> (/2).sum $ triPolyMap [(2,(23,3),(12,1),(0,0)),
(13,(12,2),(7,3),(5,3))]

4.0277004e7

========================================

>triPolyCalc :: [(Double,
> (Double, Double),
> (Double, Double),
> (Double, Double))]
> -> Double


>triPolyCalc = (sum.triPolyMap)

========================================
BEGINNING OF THE POLY3 SERIES OF FUNCTIONS

poly3 is the same function as triPoly above, with the elements rearranged so
as to make it easier to use in the building of curried formulas that can
then be mapped against a list of values of x, y, and z.

>poly3 :: forall d. Floating d => (d, d, d) -> (d, d, d, d) -> d

>poly3 (0,0,0) (a,xe,ye,ze) = 0
>poly3 (x,y,z) (a,xe,ye,ze) =
> product [a,x'**xe,y'**ye,z'**ze]
> where
> x' |x == 0 = 1
> |otherwise = x
> y' |y == 0 = 1
> |otherwise = y
> z' |z == 0 = 1
> |otherwise = z


========================================

>poly3Map :: forall c.
> Floating c =>
> (c, c, c) -> [(c, c, c, c)] -> [c]


>poly3Map (x,y,z) = map (poly3 (x,y,z))

========================================

>poly3Calc :: forall c.
> Floating c =>
> (c, c, c) -> [(c, c, c, c)] -> c

>poly3Calc (x,y,z) xs = sum $ poly3Map (x,y,z) xs

========================================
this maps a function over a list of tuples representing the values of x,y,
and z


>poly3CalcMapper xs = map ((flip poly3Calc) xs)


========================================
{ added 2006-06-27 }
These functions are just for convenient display, one per line of the results of the application of poly3CalcMapper which is integrated with the formatter.
So applying the new function poly3CalcMapperPrn applies poly3CalcMapper to
the data set and then prints the results one per line.. non generic in that
at this time it is for screen/console output, but .. well another day.


=== putAnyL -- print the contents of any list ===
Well almost any list... actually any list whose elements at the top level
are of the typeclass Show.


>putAnyL :: forall a. Show a => [a] -> IO ()
>putAnyL xs = putStrLn $ xs >>= concatMap (flip (++) "\n").(map show).return

USAGE: These examples show a one deep list of numbers, and a list of a
couple of tuples of tuples... two top level tuples as can more
easily be seen after the printout.

*TriPoly> putAnyL $ map sqrt [2..9]
1.4142135623730951
1.7320508075688772
2.0
2.23606797749979
2.449489742783178
2.6457513110645907
2.8284271247461903
3.0

*TriPoly> putAnyL [(("name","Gene"),
("age",56),
("employment","Student of Computation")),
(("name","Allen"),
("age",49),
("employment","brick layer"))]

(("name","Gene"),("age",56),("employment","Student of Computation"))
(("name","Allen"),("age",49),("employment","brick layer"))



=== poly3CalcMapperPrn prints the results after calculating them =

>poly3CalcMapperPrn :: forall c.
> Floating c =>
> [(c, c, c, c)] -> [(c, c, c)] -> IO ()

>poly3CalcMapperPrn xs ys = putAnyL $ poly3CalcMapper xs ys

USAGE:
In the function invocation below, the second list represented by:
[(a,b,c) |a <- [2,5..9],b <- [2,7..11],c <- [40,42..43]] expands to:

[(2,2,40),(2,2,42),(2,7,40),(2,7,42),(5,2,40),(5,2,42),
(5,7,40),(5,7,42),(8,2,40),(8,2,42),(8,7,40),(8,7,42)]

*TriPoly> poly3CalcMapperPrn [(24,2,0,1),(13,3,5,7)]
[(a,b,c) |a <- [2,5..9],b <- [2,7..11],c <- [40,42..43]]

5.4525952000384e14
7.67234901053376e14
1.062556550566016e15
2.8638052352000384e17
4.029661556855142e17
5.580746232903804e17
4.239938027520004e18
5.966018590559703e18
8.262439737168499e18
8.519680000024e15
1.19880453289212e16
1.66024461025544e16
4.474695680000024e18
6.296346182586121e18
8.719915988912155e18
6.6249031680000025e19
9.321904047749533e19
1.2910062089325776e20
3.489660928006144e16
4.910303366722253e16
6.800361923602227e16
1.8328353505280061e19
2.5789833963872715e19
3.571677589058414e19
2.7135603376128007e20
3.818251897958208e20
5.287961431787837e20


================== The end for now.....
Module: PigLatin
Author: Eugene Arthur
Date Started: 2006-09-07
Last Updated: 2006-09-07

Purpose: Just have a bit of fun building a short little function that
converts sentences into pig latin. Mostly to show how easy it is
in Haskell

Copyright (C) 2006 Eugene Arthur mailto:Gene<yumagene@gmail.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

>module PigLatin where

================ Function mapHeads ============
Purpose: To define a map function that maps a function to all the heads of
a list except the last one.


mapHeads f x:xs
|x == [] = []
|xs == [] = x
|otherwise = (f x) : mapHeads f xs

================ Function toPig =========
This function converts one word to pig latin..

>toPig :: [Char] -> [Char]
>toPig oneWord
> | elem (head oneWord) "aeiouyAEIOUY" = oneWord ++ "ay"
> | otherwise = toPig ((tail oneWord) ++ [head oneWord])


================ Function line2Pig ========

line2Pig disassembles a line of text into the word components
maps toPig over the resultant list to change them into pig latin
then concats the spaces back into the word list and subsequently
folds the individual words with the spaces add back into one string.


>line2Pig :: String -> String
>line2Pig = unwords.(map toPig).(words)

---------
here is a run of line2Pig using ghci the GHC interpreter.


Loading package base-1.0 ... linking ... done.
Compiling PigLatin ( PigLatin.lhs, interpreted )
Ok, modules loaded: PigLatin.

*PigLatin> :b PigLatin
line2Pig :: String -> String
toPig :: [Char] -> [Char]

*PigLatin> line2Pig "this is a line of text that will be
converted to pig latin"

"isthay isay aay inelay ofay exttay atthay illway ebay onvertedcay otay igpay atinlay"

*PigLatin>

Well now wasn't that just exciting..
-- gene

A Couple Of Haskell 2 Liners

Module: Hprimes
Author: Eugene Arthur
Date Started: 2006/12/14
Last Updated: 2006/12/14

Purpose: This is to build a naive, working, but totally non optimised
Prime Number Generator. Constructed to show how one line list
comprehensions can be used to solve a problem with ease
using Haskell. This was about a 35 minute adventure to this
point.


Copyright (C) 2006 Eugene Arthur mailto:Gene<yumagene@gmail.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation version 2 of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

========================================================================

>module Hprimes where

===== Function: factors
This function uses a list comprehension to find the factors
of any positive integer.

>factors :: forall a. Integral a => a -> [a] -- type signature
>factors x = [z |z <- [2..(div x 2)],mod x z == 0] -- code

Usage: Function factors using ghci:

*Hprimes> factors 7196
[2,4,7,14,28,257,514,1028,1799,3598]
*Hprimes> factors 887356
[2,4,97,194,388,2287,4574,9148,221839,443678]


===== Function: primeTo
This function will find the primes numbers up to an upper
limit. Another list comprehension...

>primeTo :: forall a. (Eq [a], Integral a) => a -> [a] -- type signature
>primeTo a = [x |x <- [2..a],factors x == []] -- code

Usage: Function primeTo using ghci:

*Hprimes> primeTo 200
2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,
67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,
139,149,151,157,163,167,173,179,181,191,193,197,199]


===== Function: primeFromTo
This function will find the primes
numbers from a lower limit up to an upper
limit. Another list comprehension...


>primeFromTo :: forall a. (Eq [a], Integral a) => a -> a -> [a] -- type signature
>primeFromTo a b = [x |x <- [a..b],factors x == []] -- code

Usage: Function primeFromTo using ghci:

*Hprimes> primeFromTo 234 400
[239,241,251,257,263,269,271,277,281,283,293,307,311,
313,317,331,337,347,349,353,359,367,373,379,383,389,
397]
--------------- END Hprimes ----------------