Documentation
¶
Overview ¶
Package mostlyadequate is meant to serve as a go "companion" resource to Professor Frisby's Mostly Adequate Guide.
Example (Application) ¶
package main import ( "context" "fmt" "net/http" "regexp" A "github.com/IBM/fp-go/array" E "github.com/IBM/fp-go/either" F "github.com/IBM/fp-go/function" J "github.com/IBM/fp-go/json" S "github.com/IBM/fp-go/string" R "github.com/IBM/fp-go/context/readerioeither" H "github.com/IBM/fp-go/context/readerioeither/http" ) type ( FlickrMedia struct { Link string `json:"m"` } FlickrItem struct { Media FlickrMedia `json:"media"` } FlickrFeed struct { Items []FlickrItem `json:"items"` } ) func (f FlickrMedia) getLink() string { return f.Link } func (f FlickrItem) getMedia() FlickrMedia { return f.Media } func (f FlickrFeed) getItems() []FlickrItem { return f.Items } func main() { // pure host := "api.flickr.com" path := "/services/feeds/photos_public.gne" query := S.Format[string]("?tags=%s&format=json&jsoncallback=?") url := F.Flow2( query, S.Format[string](fmt.Sprintf("https://%s%s%%s", host, path)), ) // flick returns jsonP, we extract the JSON body, this is handled by jquery in the original code sanitizeJSONP := Replace(regexp.MustCompile(`(?s)^\s*\((.*)\)\s*$`))("$1") // parse jsonP parseJSONP := F.Flow3( sanitizeJSONP, S.ToBytes, J.Unmarshal[FlickrFeed], ) // markup img := S.Format[string]("<img src='%s'/>") // lenses mediaURL := F.Flow2( FlickrItem.getMedia, FlickrMedia.getLink, ) mediaURLs := F.Flow2( FlickrFeed.getItems, A.Map(mediaURL), ) images := F.Flow2( mediaURLs, A.Map(img), ) client := H.MakeClient(http.DefaultClient) // func(string) R.ReaderIOEither[[]string] app := F.Flow5( url, H.MakeGetRequest, H.ReadText(client), R.ChainEitherK(parseJSONP), R.Map(images), ) // R.ReaderIOEither[[]string] // this is the managed effect that can be called to download and render the images catImageEffect := app("cats") // impure, actually executes the effect catImages := catImageEffect(context.TODO())() fmt.Println(E.IsRight(catImages)) }
Output: true
Example (Dasherize) ¶
fmt.Println(Dasherize("The world is a vampire"))
Output: the-world-is-a-vampire
Example (Flock) ¶
package main import "fmt" type Flock struct { Seagulls int } func MakeFlock(n int) Flock { return Flock{Seagulls: n} } func (f *Flock) Conjoin(other *Flock) *Flock { f.Seagulls += other.Seagulls return f } func (f *Flock) Breed(other *Flock) *Flock { f.Seagulls = f.Seagulls * other.Seagulls return f } func main() { flockA := MakeFlock(4) flockB := MakeFlock(2) flockC := MakeFlock(0) fmt.Println(flockA.Conjoin(&flockC).Breed(&flockB).Conjoin(flockA.Breed(&flockB)).Seagulls) }
Output: 32
Example (GetAge) ¶
now, err := time.Parse(time.DateOnly, "2023-09-01") if err != nil { panic(err) } fmt.Println(GetAge(now)(MakeUser("2005-12-12"))) fmt.Println(GetAge(now)(MakeUser("July 4, 2001"))) fortune := F.Flow3( N.Add(365.0), S.Format[float64]("%0.0f"), Concat("If you survive, you will be "), ) zoltar := F.Flow3( GetAge(now), E.Map[error](fortune), E.GetOrElse(errors.ToString), ) fmt.Println(zoltar(MakeUser("2005-12-12")))
Output: Right[float64](6472) Left[*time.ParseError](parsing time "July 4, 2001" as "2006-01-02": cannot parse "July 4, 2001" as "2006") If you survive, you will be 6837
Example (Greeting) ¶
package main import "fmt" func Hi(name string) string { return fmt.Sprintf("Hi %s", name) } func Greeting(name string) string { return Hi(name) } func main() { // functions are first class objects greet := Hi fmt.Println(Greeting("times")) fmt.Println(greet("times")) }
Output: Hi times Hi times
Example (Pipe) ¶
output := F.Pipe2( "send in the clowns", ToUpper, Exclaim, ) fmt.Println(output)
Output: SEND IN THE CLOWNS!
Example (RenderPage) ¶
// prepare the http client client := H.MakeClient(http.DefaultClient) // get returns the title of the nth item from the REST service get := F.Flow4( idxToURL, H.MakeGetRequest, H.ReadJSON[PostItem](client), R.Map(PostItem.getTitle), ) res := F.Pipe2( R.Of(renderString), // start with a function with 2 unresolved arguments R.Ap[func(string) string](get(1)), // resolve the first argument R.Ap[string](get(2)), // in parallel resolve the second argument ) // finally invoke in context and start fmt.Println(res(context.TODO())())
Output: Right[string](<div>Destinations: [qui est esse], Events: [ea molestias quasi exercitationem repellat qui ipsa sit aut]</div>)
Example (Shout) ¶
fmt.Println(Shout("send in the clowns"))
Output: SEND IN THE CLOWNS!
Example (Solution04A) ¶
// words :: String -> [String] words := Split(regexp.MustCompile(` `)) fmt.Println(words("Jingle bells Batman smells"))
Output: [Jingle bells Batman smells]
Example (Solution04B) ¶
// filterQs :: [String] -> [String] filterQs := A.Filter(Matches(regexp.MustCompile(`q`))) fmt.Println(filterQs(A.From("quick", "camels", "quarry", "over", "quails")))
Output: [quick quarry quails]
Example (Solution04C) ¶
keepHighest := N.Max[int] // max :: [Number] -> Number max := A.Reduce(keepHighest, math.MinInt) fmt.Println(max(A.From(323, 523, 554, 123, 5234)))
Output: 5234
Example (Solution05A) ¶
IsLastInStock := F.Flow2( A.Last[Car], O.Map(Car.getInStock), ) fmt.Println(IsLastInStock(Cars[0:3])) fmt.Println(IsLastInStock(Cars[3:]))
Output: Some[bool](true) Some[bool](false)
Example (Solution05B) ¶
// averageDollarValue :: [Car] -> Int averageDollarValue := F.Flow2( A.Map(Car.getDollarValue), average, ) fmt.Println(averageDollarValue(Cars))
Output: 790700
Example (Solution05C) ¶
// order by horsepower ordByHorsepower := ord.Contramap(Car.getHorsepower)(I.Ord) // fastestCar :: [Car] -> Option[String] fastestCar := F.Flow3( A.Sort(ordByHorsepower), A.Last[Car], O.Map(F.Flow2( Car.getName, S.Format[string]("%s is the fastest"), )), ) fmt.Println(fastestCar(Cars))
Output: Some[string](Aston Martin One-77 is the fastest)
Example (Solution08A) ¶
incrF := I.Map(N.Add(1)) fmt.Println(incrF(I.Of(2)))
Output: 3
Example (Solution08B) ¶
// initial :: User -> Option rune initial := F.Flow3( Chapter08User.getName, S.ToRunes, A.Head[rune], ) fmt.Println(initial(albert08))
Output: Some[int32](65)
Example (Solution08C) ¶
// eitherWelcome :: User -> Either String String eitherWelcome := F.Flow2( checkActive, E.Map[error](showWelcome), ) fmt.Println(eitherWelcome(gary08)) fmt.Println(eitherWelcome(theresa08))
Output: Left[*errors.errorString](your account is not active) Right[string](Welcome Theresa)
Example (Solution08D) ¶
// // validateName :: User -> Either String () validateName := F.Flow3( Chapter08User.getName, E.FromPredicate(F.Flow2( S.Size, ord.Gt(ord.FromStrictCompare[int]())(3), ), errors.OnSome[string]("Your name %s is larger than 3 characters")), E.Map[error](F.ToAny[string]), ) saveAndWelcome := F.Flow2( save, IOE.Map[error](showWelcome), ) register := F.Flow3( validateUser(validateName), IOE.FromEither[error, Chapter08User], IOE.Chain(saveAndWelcome), ) fmt.Println(validateName(gary08)) fmt.Println(validateName(yi08)) fmt.Println(register(albert08)()) fmt.Println(register(yi08)())
Output: Right[string](Gary) Left[*errors.errorString](Your name Yi is larger than 3 characters) Right[string](Welcome Albert) Left[*errors.errorString](Your name Yi is larger than 3 characters)
Example (Solution09A) ¶
// // getStreetName :: User -> Maybe String getStreetName := F.Flow4( Chapter09User.getAddress, Address.getStreet, Street.getName, O.FromPredicate(S.IsNonEmpty), ) fmt.Println(getStreetName(albert09)) fmt.Println(getStreetName(gary09)) fmt.Println(getStreetName(theresa09))
Output: Some[string](Walnut St) None[string] None[string]
Example (Solution09B) ¶
logFilename := F.Flow2( io.Map(path.Base), io.ChainFirst(pureLog), ) fmt.Println(logFilename(getFile)())
Output: ch09.md
Example (Solution09C) ¶
// // joinMailingList :: Email -> Either String (IO ()) joinMailingList := F.Flow4( validateEmail, IOE.FromEither[error, string], IOE.Chain(addToMailingList), IOE.Chain(emailBlast), ) fmt.Println(joinMailingList("sleepy@grandpa.net")()) fmt.Println(joinMailingList("notanemail")())
Output: Right[string](sleepy@grandpa.net) Left[*errors.errorString](email notanemail is invalid)
Example (Solution10A) ¶
safeAdd := F.Curry2(func(a, b O.Option[int]) O.Option[int] { return F.Pipe3( N.Add[int], O.Of[func(int) func(int) int], O.Ap[func(int) int](a), O.Ap[int](b), ) }) fmt.Println(safeAdd(O.Of(2))(O.Of(3))) fmt.Println(safeAdd(O.None[int]())(O.Of(3))) fmt.Println(safeAdd(O.Of(2))(O.None[int]()))
Output: Some[int](5) None[int] None[int]
Example (Solution10B) ¶
safeAdd := F.Curry2(T.Untupled2(F.Flow2( O.SequenceTuple2[int, int], O.Map(T.Tupled2(N.MonoidSum[int]().Concat)), ))) fmt.Println(safeAdd(O.Of(2))(O.Of(3))) fmt.Println(safeAdd(O.None[int]())(O.Of(3))) fmt.Println(safeAdd(O.Of(2))(O.None[int]()))
Output: Some[int](5) None[int] None[int]
Example (Solution10C) ¶
// startGame :: IO String startGame := F.Pipe2( IOO.Of(game), IOO.Ap[func(Player) string](getFromCache("player1")), IOO.Ap[string](getFromCache("player2")), ) startGameTupled := F.Pipe2( T.MakeTuple2("player1", "player2"), IOO.TraverseTuple2(getFromCache, getFromCache), IOO.Map(T.Tupled2(func(a, b Player) string { return fmt.Sprintf("%s vs %s", a.Name, b.Name) })), ) fmt.Println(startGame()) fmt.Println(startGameTupled())
Output: Some[string](Albert vs Theresa) Some[string](Albert vs Theresa)
Example (Solution11A) ¶
// eitherToMaybe :: Either b a -> Maybe a eitherToMaybe := E.ToOption[error, string] fmt.Println(eitherToMaybe(E.Of[error]("one eyed willy"))) fmt.Println(eitherToMaybe(E.Left[string](fmt.Errorf("some error"))))
Output: Some[string](one eyed willy) None[string]
Example (Solution11B) ¶
findByNameID := F.Flow2( findUserByID, IOE.Map[error](Chapter08User.getName), ) fmt.Println(findByNameID(1)()) fmt.Println(findByNameID(2)()) fmt.Println(findByNameID(3)()) fmt.Println(findByNameID(4)())
Output: Right[string](Albert) Right[string](Gary) Right[string](Theresa) Left[*errors.errorString](user 4 not found)
Example (Solution11C) ¶
// strToList :: String -> [Char strToList := Split(regexp.MustCompile(``)) // listToStr :: [Char] -> String listToStr := A.Intercalate(S.Monoid)("") sortLetters := F.Flow3( strToList, A.Sort(S.Ord), listToStr, ) fmt.Println(sortLetters("sortme"))
Output: emorst
Example (Solution12A) ¶
// getJsons :: Map Route Route -> Task Error (Map Route JSON) getJsons := IOE.TraverseRecord[string](httpGet) fmt.Println(getJsons(routes)())
Output: Right[map[string]string](map[/:json for / /about:json for /about])
Example (Solution12B) ¶
// startGame :: [Player] -> [Either Error String] startGame := F.Flow2( E.TraverseArray(validatePlayer), E.MapTo[error, []Player]("Game started"), ) fmt.Println(startGame(A.From(playerAlbert, playerTheresa))) fmt.Println(startGame(A.From(playerAlbert, Player{Id: 4})))
Output: Right[string](Game started) Left[*errors.errorString](player 4 must have a name)
Example (Solution12C) ¶
traverseO := O.Traverse[string]( IOE.Of[error, O.Option[string]], IOE.Map[error, string, O.Option[string]], ) // readFirst :: String -> Task Error (Maybe String) readFirst := F.Pipe2( readdir, IOE.Map[error](A.Head[string]), IOE.Chain(traverseO(readfile("utf-8"))), ) fmt.Println(readFirst())
Output: Right[option.Option[string]](Some[string](content of file1 (utf-8)))
Example (Street) ¶
s := FirstAddressStreet(AddressBook{ Addresses: A.From(Address{Street: Street{Name: "Mulburry", Number: 8402}, Postcode: "WC2N"}), }) fmt.Println(s)
Output: Some[mostlyadequate.Street]({Mulburry 8402})
Example (Widthdraw) ¶
fmt.Println(getTwenty(MakeAccount(200))) fmt.Println(getTwenty(MakeAccount(10)))
Output: Your balance is $180.00 You're broke!
Index ¶
Examples ¶
- Package (Application)
- Package (Dasherize)
- Package (Flock)
- Package (GetAge)
- Package (Greeting)
- Package (Pipe)
- Package (RenderPage)
- Package (Shout)
- Package (Solution04A)
- Package (Solution04B)
- Package (Solution04C)
- Package (Solution05A)
- Package (Solution05B)
- Package (Solution05C)
- Package (Solution08A)
- Package (Solution08B)
- Package (Solution08C)
- Package (Solution08D)
- Package (Solution09A)
- Package (Solution09B)
- Package (Solution09C)
- Package (Solution10A)
- Package (Solution10B)
- Package (Solution10C)
- Package (Solution11A)
- Package (Solution11B)
- Package (Solution11C)
- Package (Solution12A)
- Package (Solution12B)
- Package (Solution12C)
- Package (Street)
- Package (Widthdraw)
Constants ¶
This section is empty.
Variables ¶
View Source
var ( Cars = A.From(Car{ Name: "Ferrari FF", Horsepower: 660, DollarValue: 700000, InStock: true, }, Car{ Name: "Spyker C12 Zagato", Horsepower: 650, DollarValue: 648000, InStock: false, }, Car{ Name: "Jaguar XKR-S", Horsepower: 550, DollarValue: 132000, InStock: true, }, Car{ Name: "Audi R8", Horsepower: 525, DollarValue: 114200, InStock: false, }, Car{ Name: "Aston Martin One-77", Horsepower: 750, DollarValue: 1850000, InStock: true, }, Car{ Name: "Pagani Huayra", Horsepower: 700, DollarValue: 1300000, InStock: false, }) )
Functions ¶
This section is empty.
Types ¶
Click to show internal directories.
Click to hide internal directories.