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

**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

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

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

- Current Location:Dungeon -{home office}
- Current Mood: okay
- Current Music:furnace

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,9

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,1

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

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,9

-------

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,2

-----

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,2

------

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","bloat

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!!

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)

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

- Current Location:home office
- Current Mood: working
- Current Music:none right now..

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)

-------

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

[(60.0,7.937253933193772),(55.0,7.615773

(45.0,6.928203230275509),(40.0,6.5574385

(30.0,5.744562646538029),(25.0,5.2915026

(15.0,4.242640687119285),(10.0,3.6055512

--------

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,1

(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))

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

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,Fal

False,False,False,False,False,False,Fals

======= 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),(("c

(("cow",7),False),(("cow",8),False),(("h

(("horse",4),True),(("horse",5),False),(

*PairsLogic> mapPairTestWpairs (||) (=="horse") (<5) [(animal,age) |animal <- ["cow","horse","pig"],age <- [1..8]]

[(("cow",1),True),(("cow",2),True),(("co

(("cow",7),False),(("cow",8),False),(("h

(("horse",4),True),(("horse",5),True),((

======== 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)

- Current Location:Home Office
- Current Mood: working
- Current Music:bit of Bonnie Raitt

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"

(("name","Allen"),("age",49),("employmen

=== 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,4

(5,7,40),(5,7,42),(8,2,40),(8,2,42),(8,7,4

*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.....

- Current Location:Home Office
- Current Music:Humming fan

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

- Current Location:office {home}
- Current Mood: groggy
- Current Music:Dylan's Who Killed Davey Moore"

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,44

===== 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,5

67,71,73,79,83,89,97,101,103,107,109,113,1

139,149,151,157,163,167,173,179,181,191,1

===== 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,2

313,317,331,337,347,349,353,359,367,373,3

397]

--------------- END Hprimes ----------------

- Current Location:Home Office
- Current Mood: awake
- Current Music:silence