ity]
24 val usa = Country("USA", 25 List( 26 City("Washington"), City("New York"))) 27 //> usa : Exercises.kli.Country = Country(USA,List(City(Washington,false,20), 28 //| City(New York,false,20)))
29 cities(usa) //> res9: List[Exercises.kli.City] = List(City(Washington,false,20), City(New Y 30 //| ork,false,20))
从continents,countries,cities这三个函数运算结果可以看出它们都可以独立运算。这三个函数的款式如下:
String => List[Continent]
Continent => List[Country]
Country => List[City]
无论函数款式或者类封套(List本来就是Monad)都适合Kleisli。我们可以用Kleisli把这三个局部函数用各种方法组合起来实现更广泛功能:
1 val allCountry = kleisli(continents) >==> countries 2 //> allCountry : scalaz.Kleisli[List,String,Exercises.kli.Country] = Kleisli(< 3 //| function1>)
4 val allCity = kleisli(continents) >==> countries >==> cities 5 //> allCity : scalaz.Kleisli[List,String,Exercises.kli.City] = Kleisli(<functi 6 //| on1>)
7 allCountry("Amer") //> res10: List[Exercises.kli.Country] = List(Country(USA,List(City(Washington, 8 //| false,20), City(New York,false,20))))
9 allCity("Amer") //> res11: List[Exercises.kli.City] = List(City(Washington,false,20), City(New 10 //| York,false,20))
还有个=<<符号挺有意思:
1 def =<<(a: M[A])(implicit m: Bind[M]): M[B] = m.bind(a)(run)
意思是用包嵌的函数flatMap一下输入参数M[A]:
1 allCity =<< List("Amer","Asia") //> res12: List[Exercises.kli.City] = List(City(Washington,false,20), City(New 2 //| York,false,20), City(New Dehli,false,20), City(Calcutta,false,20))
那么如果我想避免使用List(),用Option[List]作为函数输出可以吗?Option是个Monad,第一步可以通过。下一步是把函数款式对齐了:
List[String] => Option[List[Continent]]
List[Continent] => Option[List[Country]]
List[Country] => Option[List[City]]
下面是这三个函数的升级版:
1 //查找Continent List[String] => Option[List[Continent]]
2 def maybeContinents(names: List[String]): Option[List[Continent]] =
3 names.flatMap(name => data.filter(k => k.name.contains(name))) match { 4 case h :: t => (h :: t).some 5 case _ => none 6 } //> maybeContinents: (names: List[String])Option[List[Exercises.kli.Continent]] 7 //| 8 //测试运行
9 maybeContinents(List("Amer","Asia")) //> res13: Option[List[Exercises.kli.Continent]] = Some(List(Continent(America, 10 //| List(Country(USA,List(City(Washington,false,20), City(New York,false,20)))) 11 //| ), Continent(Asia,List(Country(India,List(City(New Dehli,false,20), City(Ca 12 //| lcutta,false,20))))))) 13 //查找Country List[Continent] => Option[List[Country]]
14 def maybeCountries(continents: List[Continent]): Option[List[Country]] =
15 continents.flatMap(continent => continent.countries.map(c => c)) match { 16 case h :: t => (h :: t).some 17 case _ => none 18 } //> maybeCountries: (continents: List[Exercises.kli.Continent])Option[List[Exer 19 //| cises.kli.Country]] 20 //查找City List[Country] => Option[List[Country]]
21 def maybeCities(countries: List[Country]): Option[List[City]] =
22 countries.flatMap(country => country.cities.map(c => c)) match { 23 case h :: t => (h :: t).some 24 case _ => none 25 } //> maybeCities: (countries: List[Exercises.kli.Country])Option[List[Exercises. 26 //| kli.City]]
27
28 val |