ä»æ¥ã¯ãã«ãªã¼åã¨é¢æ°ã®é¨åé©ç¨ã®è©±é¡ã
Haskellã®è¦åº§ããScalaã®ã«ãªã¼åã¨é¨åé©ç¨ãè¦ã¦ã¿ã
ã¾ããHaskellã§ã®é¢æ°ã®ã«ãªã¼åã¨é¨åé©ç¨ã«ã¤ãã¦ããããã
ä¾ãã°ãå¼æ°ãåè¨ããé¢æ° mysum ãããã¨ãã¦ã
mysum :: Num a => a -> a -> a -> a mysum a b c = a + b + c
次ã®ããã«ããã¨å½ç¶æå¾ å¤ãå¾ããã¨ãã§ãã¾ããã¾ãå½ç¶ã§ãã...ã
ghci> mysum 1 2 3 6
ãããããã®ã³ã¼ããJavaè³ãç¨ãã¦èªãã å ´åã
mysum(1,2,3)
ã®ããã«èªãã§ãã¾ããã¡ã§ããã次ã®ããã«èªãã®ãæ£è§£ã§ãã
((mysum 1) 2) 3
Haskellã§ã¯é¢æ°ã¯å¿ ãä¸ã¤ã®å¼æ°ãåãã¨ããèãæ¹ãããã2åç®ã®å¼æ°ã¯1ã¤ç®ã®å¼æ°ãåãé¢æ°ã®å¼æ°ã¨ãã¦æ¸¡ããã¾ãã3ã¤ç®ä»¥éãåæ§ã§ãããããé¢æ°ãã«ãªã¼åããã¦ããã¨ããã¾ãã
ãã®mysum
é¢æ°ã§èãã¦ã¿ãã¨ãmysum
ã¯a -> (a -> a -> a)
ã§ããã¤ã¾ãå¼æ°ãä¸ã¤åãã(a -> a -> a)ã¨ããé¢æ°ãæ»ãå¤ã¨ãã¦è¿ãé¢æ°ã¨è¨ããã
ã¾ããå¼æ°ãé¨åçç¨ãããmysum 1
ã¯a -> (a -> a)
ã§ããã¤ã¾ãå¼æ°ãä¸ã¤åãã(a -> a)ã¨ããé¢æ°ãæ»ãå¤ã¨ãã¦è¿ãé¢æ°ã
å¼æ°ãé¨åçç¨ãããmysum 1 2
ã¯a -> a
ã§ããã¤ã¾ãå¼æ°ãä¸ã¤åãè¨ç®çµæãæ»ãå¤ã¨ãã¦è¿ãé¢æ°ãã¨ãããã¨ãè¨ãã¾ãã
ghci> :t mysum mysum :: Num a => a -> a -> a -> a ghci> :t mysum 1 mysum 1 :: Num a => a -> a -> a ghci> :t mysum 1 2 mysum 1 2 :: Num a => a -> a
ãã®ä»çµã¿ãå©ç¨ããã¨ãå¼æ°ãé¨åé©ç¨ããé¢æ°ãå¾ã¦ãæ®ãã®å¼æ°ãå¾ã§é©ç¨ã§ããããã§ãããããªæãã
ghci> let mysum_1 = mysum 1 ghci> mysum_1 2 3 6
Scalaã§ãã«ãªã¼åã¨å¼æ°ã®é¨åé©ç¨ãã§ãã¾ãã
話ãé¸ãã¾ãããScalaã¯å¼æ°ã®ãªã¹ããè¤æ°åå®ç¾©ã§ãã¾ãã
scala> def sum(a:Int)(b:Int)(c:Int):Int = a + b + c
sum: (a: Int)(b: Int)(c: Int)Int
å¼æ°ãé¨åé©ç¨ããã«æ®éã«å¼ã³åºãã«ã¯ãããªæãã
scala> sum(1)(2)(3) res0: Int = 6
é¨åé©ç¨ããé¢æ°ã欲ãããã°ã次ã®ããã«ããã°ããã§ãã*1
scala> val sum_1 = sum(1) _ sum_1: Int => (Int => Int) = <function1> scala> sum_1(2)(3) res0: Int = 6
sum_1ã¯ã«ãªã¼åããã¦ããã®ã§ãããsumèªä½ã¯ã«ãªã¼åããã¦ãã¾ãããInt => Int => Int => Int
ã¨ããåã®é¢æ°ã«ãªã£ã¦ããªãããã§ããããããããã®ã§ãããsumã¯è¤æ°ã®å¼æ°ãªã¹ããæã£ã¦ããã ãã§ãã«ãªã¼åããã¦ããããã§ãªãã£ã¦ãã¨ã§ããã
次ã®ããã«ããã¨ã«ãªã¼åãããã¡ã½ãããå®ç¾©ã§ãã¾ã*2ã
scala> def sum(a:Int) = (b:Int) => (c:Int) => a + b + c
sum: (a: Int)Int => (Int => Int)
ã¾ãã次ã®ãããªã«ãªã¼åããã¦ããªãé¢æ°ãã«ãªã¼ãããå ´åã¯curriedã¡ã½ãã*3ã使ãã¾ãã
scala> def sum(a:Int, b:Int, c:Int):Int = a + b + c scala> val sum_curried = (sum _).curried sum_crried: Int => (Int => (Int => Int)) = <function1>
Haskellã®é¢æ°å®ç¾©ã¨åããããªå½¢å¼ã®é¢æ°ã«å¤æããã¾ããããã¹ã¦ã®å¼æ°ãFunction1åé¢æ°ã®çµã¿åããã§å¦çããæ§é ã«å¤ããã¾ããã Haskellã¨åæ§ã«å¼æ°ã«é¨åé©ç¨ããé¢æ°ã«æ®ãã®å¼æ°ãé©ç¨ããã°è¨ç®çµæãå¾ããã¾ãã
scala> val sum_1 = sum_curried(1) sum_1: Int => (Int => Int) = <function1> scala> sum_1(2)(3) res0: Int = 6
Dxoã§ã®å®ä¾
ã§ãã©ãããã¨ããã§ä½¿ããããï¼ã£ã¦å£°ãèããã¦ããããªã®ã§ãScala(Scalaz)ã§ã®å®ä¾ãèãã¦ã¿ã¾ããã
ãã¡ã¤ã³ã®ç°ãªããªãã¸ã§ã¯ããç¸äºã«å¤æããããã®ãªãã¸ã§ã¯ãã§ãããDxoã®å®ä¾ãç´¹ä»ãã¾ãã
Dxoã¯ã·ã³ãã«ãªFunctorã®å®è£ ã§ãDxoã®å¤(value)ã«mapã®å¼æ°ã«ä¸ããé¢æ°fãé©ç¨ããã ãã§ããé©ç¨ããã¨fã«ãã£ã¦å¤æããããªãã¸ã§ã¯ããè¿ã£ã¦ãã¾ãã ãã ãããã®é¢æ°ã¯f : A => Bã§ãªããã°ãªãã¾ããããã®ã³ã¼ãä¾ã¯ãUserAããUserBã¸ã®å¤æã示ãã¦ãã¾ãã
import scalaz._ import Scalaz._ case class UserA(name:String) case class UserB(fname:String, lname:String) case class Dxo[A](value:A) object Dxo { implicit object Functor extends Functor[Dxo] { def map[A, B](fa: Dxo[A])(f: A => B): Dxo[B] = { Dxo(f(fa.value)) } } } object Main extends App { val create = {a:UserA => val names = a.name.split(":"); UserB(names(0), names(1))} val append = {(b:UserB, a:UserA) => UserB(b.fname+":"+a.name, b.lname+":"+a.name)}.curried val userB1 = Dxo(UserA("junichi:kato")) map create val userB2 = Dxo(UserA("junichi:kato")) map append(UserB("hoge", "fuga")) println(userB1.value) println(userB2.value) }
createé¢æ°ã¯å¼æ°ã«UserAãåã£ã¦ãUserA#nameã":"ã§åå²ããUserBã«å¤æãã¦è¿ãé¢æ°ã§ããé¢æ°ã®åã¯UserA => UserB
ã§ãã
val create = {a:UserA => val names = a.name.split(":"); UserB(names(0), names(1))} val userB1 = Dxo(UserA("junichi:kato")) map create
ã¨ãããã¾ã§ãã£ã¦ããã¨ã¯å ·ä½çãªå¤æå¦çãcreateé¢æ°ã«å®ç¾©ãã¦å¼ã³åºãã¦ããã ããªã®ã§åç´ã§ãã
ããããã«ãªã¼åã¨é¨åé©ç¨ã®åºçªã§ãã
Dxo#mapã¯UserAããUserBãå¾ããã¨ãªã£ã¦ããã®ã§ãããæå
ã«ãã§ã«UserBã®ã¤ã³ã¹ã¿ã³ã¹ãããå ´åã¯(b:UserB, a:UserA) => UserB
ã®å½¢å¼ã®é¢æ°ãèããããªãã¾ãã
ãã®ä¾ã®appendé¢æ°ã¯ãé©å½ã«æ¢åã®UserBã¨UserAãçµã¿åããã¦æ°ããUserBãçã¿åºãé¢æ°ã§ããããã®ã¾ã¾ããmapã¡ã½ããã«æ¸¡ããã¨ãã§ãã¾ãããUserA => UserB
ã®åã§ãªããã°ãªãã¾ããã
ããã§curriedã§ã«ãªã¼åããããã§ããã
ã«ãªã¼åããé¢æ°ã«ç¬¬ä¸å¼æ°ã§ããUserBãé¨åé©ç¨ãã¾ããããããã¨ãappend(UserB("hoge", "fuga"))
ã¯é¨åé©ç¨ãããé¢æ°ãªã®ã§ãæ®ãã®å¼æ°ã¯UserAã®ã¿ã¨ãªãã®ã§é¢æ°ã®åã¯UserA => UserB
ã¨ãªãããã§ã*4ãmapå¦çã®å¼ã³åºãã¯ããªãã¨ãªãDSLã£ã½ãè¦ãã¦ããæãã§ããã
val append = {(b:UserB, a:UserA) => UserB(b.fname+":"+a.name, b.lname+":"+a.name)}.curried val userB2 = Dxo(UserA("junichi:kato")) map append(UserB("hoge", "fuga"))
ã«ãªã¼åããé¢æ°ã®é¨åé©ç¨ã¯ãé¢æ°ã®æ½è±¡åã®ããã®ã²ã¨ã¤ã®ææ³ã¨ãããã¨ã«ãªãã¾ãããã
*1:sumã¯ã¡ã½ãããªã®ã§ãé¢æ°åããã¨ãã«_
ãã¤ãã¦ãããå¿
è¦ãããã¾ã
*2:ã¡ã½ããã®åãã¡ãã£ã¨æ³å®ã¨ç°ãªãã¾ãããä¸å¿ã«ãªã¼åããã¦ãã¾ã
*3:Function2ãã22ã§å®ç¾©ããã¦ããã¡ã½ãã
*4:appendé¢æ°ã(a:UserA,b:UserB) => UserBã¨ããå½¢å¼ã®å ´åã¯ã«ãªã¼åãã¦é¨åé©ç¨ãã¦ãé¢æ°ã®åãæå³éãã«ãªããªãã®ã§æ³¨æãå¿ è¦