±à¼ÍƼö: |
±¾ÎĽ«ÓÃÈýÖÖ·½·¨À´´´½¨
CI/CD Á÷Ë®Ïß¡£Monad ²»ÄܶÔÁ÷Ë®Ïß½øÐо²Ì¬·ÖÎö£¬Arrow Óï·¨ºÜÄÑÓã¬ÎÒ³ÆÖ®Îª
Dart£¨²»ÖªµÀËüÊÇ·ñÒѾÓÐÃû×ÖÁË£©µÄÒ»ÖÖÇáÁ¿¼¶µÄ Arrow ·½·¨¿ÉÒÔÏñ Arrow
Ò»Ñù½øÐо²Ì¬·ÖÎö£¬µ«Óï·¨±È Monad ¸ü¼òµ¥¡£
±¾ÎÄÀ´×ÔÓÚinfoq£¬ÓÉ»ðÁú¹ûÈí¼þAnna±à¼ÍƼö¡£ |
|
ÎÒÐèÒª¹¹½¨Ò»¸öÓÃÓÚ´´½¨ CI/CD Á÷Ë®ÏßµÄϵͳ¡£ËüÆð³õÊÇΪÁ˹¹½¨Ò»¸ö
CI ϵͳ£¬²âÊÔ Github É쵀 OCaml ÏîÄ¿£¨Õë¶Ô¶à¸ö°æ±¾µÄ OCaml ±àÒëÆ÷ºÍ¶à¸ö²Ù×÷ϵͳ£¬²âÊÔÿ¸öÌá½»£©¡£ÏÂÃæÊÇÒ»¸ö¼òµ¥µÄÁ÷Ë®Ïߣ¬»ñȡij¸ö
Git ·ÖÖ§×îеÄÌá½»£¬¹¹½¨£¬²¢Ö´ÐвâÊÔÓÃÀý¡£
¡¾ÒëÕß×¢¡¿CI/CD£º³ÖÐø¼¯³É£¨Continuous Integration£©ºÍ³ÖÐø²¿Êð£¨Continuous
Deployment£©¼ò³Æ£¬Ö¸ÔÚ¿ª·¢¹ý³ÌÖÐ×Ô¶¯Ö´ÐÐһϵÁнű¾À´¼õµÍ¿ª·¢ÒýÈë bug µÄ¸ÅÂÊ£¬ÔÚдúÂë´Ó¿ª·¢µ½²¿ÊðµÄ¹ý³ÌÖУ¬¾¡Á¿¼õÉÙÈ˹¤µÄ½éÈë¡£

ÕâÀïµÄÅäÉ«±êʶÊÇ£ºÂÌÉ«µÄ·½¿òÊÇÒѾÍê³É£¬³ÈÉ«µÄÊÇÕýÔÚ½øÐУ¬»ÒÉ«µÄÒâζ×ÅÕâÒ»²½»¹²»ÄÜ¿ªÊ¼¡£
ÕâÀïÓÐÒ»¸öÉÔ΢¸´ÔÓµãµÄÀý×Ó£¬Ëü»¹ÏÂÔØÁËÒ»¸ö Docker »ù´¡¾µÏñ£¬Ê¹ÓÃÁ½¸ö²»Í¬°æ±¾µÄ OCaml
±àÒëÆ÷²¢Ðй¹½¨Ìá½»£¬È»ºó²âÊԵõ½µÄ¾µÏñ¡£ºì¿ò±íʾ´Ë²½Öèʧ°Ü£º

Ò»¸ö¸ü¸´ÔÓµÄÀý×ÓÊDzâÊÔÏîÄ¿±¾Éí£¬È»ºóËÑË÷ÒÀÀµËüµÄÆäËûÏîÄ¿£¬²¢¸ù¾Ýа汾²âÊÔÕâЩÏîÄ¿£º

ÔÚÕâÀԲȦÒâζ×ÅÔÚ¼ì²é·´ÏòÒÀÀµÏî֮ǰ£¬ÎÒÃÇÓ¦¸ÃµÈ´ý²âÊÔͨ¹ý¡£
ÎÒÃÇ¿ÉÒÔÓà YAML »òÀàËÆµÄ·½·¨À´ÃèÊöÕâЩ¹ÜµÀ£¬µ«Õ⽫ÊǷdz£ÓÐÏ޵ġ£Ïà·´£¬ÎÒ¾ö¶¨Ê¹ÓÃÒ»ÖÖÌØ¶¨ÓÚÁìÓòµÄǶÈëʽÓïÑÔ£¬ÕâÑùÎÒÃǾͿÉÒÔÃâ·ÑʹÓÃËÞÖ÷ÓïÑÔµÄÌØÐÔ£¨ÀýÈç×Ö·û´®²Ù×÷¡¢±äÁ¿¡¢º¯Êý¡¢µ¼Èë¡¢ÀàÐͼì²éµÈ£©¡£
×îÃ÷ÏԵķ½·¨ÊÇʹÿ¸ö¿ò³ÉΪÕýÔòº¯Êý¡£È»ºóÉÏÃæµÄµÚÒ»¸öÀý×Ó¿ÉÒÔÊÇ£¨ÕâÀʹÓÃ
OCaml Óï·¨£©£º
let example1
commit =
let src = fetch commit in
let image = build src in
test image |
µÚ¶þ¸ö¿ÉÄÜÊÇ£º
let example2
commit =
let src = fetch commit in
let base = docker_pull "ocaml/opam2"
in
let build ocaml_version =
let dockerfile = make_dockerfile ~base ~ocaml_version
in
let image = build ~dockerfile src ~label:ocaml_version
in
test image
in
build "4.07";
build "4.08" |
µÚÈý¸ö¿ÉÄÜÊÇÕâÑùµÄ£º
let example3
commit =
let src = fetch commit in
let image = build src in
test image;
let revdeps = get_revdeps src in
List.iter example1 revdeps |
²»¹ý£¬ÎÒÃÇÏëÔÚÓïÑÔÖÐÌí¼ÓһЩ¸½¼Ó¹¦ÄÜ£º
¹ÜµÀ²½ÖèÓ¦¾¡¿ÉÄܲ¢ÐÐÔËÐС£ÉÏÃæµÄ example2 º¯Êý½«Ò»´ÎÍê³ÉÒ»¸ö¹¹½¨¡£
¹ÜµÀ²½ÖèÓ¦ÔÚÆäÊäÈë¸ü¸ÄÊ±ÖØÐ¼ÆËã¡£e¡¢ µ±ÎÒÃÇ×÷³öеijÐŵʱ£¬ÎÒÃÇÐèÒªÖØ½¨¡£
Óû§Ó¦¸ÃÄܹ»²é¿´Ã¿¸ö²½ÖèµÄ½ø¶È¡£
Óû§Ó¦¸ÃÄܹ»ÎªÈκβ½Öè´¥·¢Öؽ¨¡£
ÎÒÃÇÓ¦¸ÃÄܹ»´Ó´úÂëÖÐ×Ô¶¯Éú³Éͼ±í£¬ÕâÑùÎÒÃǾͿÉÒÔÔÚÔËÐйܵÀ֮ǰ¿´µ½Ëü½«×öʲô¡£
Ò»²½µÄʧ°Ü²»Ó¦¸ÃʹÕû¸ö¹ÜµÀÍ£Ö¹¡£
¶ÔÓÚÕâÆª²©¿ÍÎÄÕÂÀ´Ëµ£¬È·Çеĸ½¼Ó¹¦Äܲ¢²»ÖØÒª£¬Òò´ËΪÁ˼òµ¥Æð¼û£¬ÎÒ½«Öصã·ÅÔÚͬʱÔËÐв½ÖèÉÏ¡£
Monad ·½·¨
¡¾ÒëÕß×¢¡¿Monad£ºº¯×Ó£¬µ¥×Ó£¬À´×Ô Haskell ±à³ÌÓïÑÔ£¬ÊǺ¯Êýʽ±à³ÌÖУ¬Ò»ÖÖ¶¨Ò彫º¯Êý£¨º¯×Ó£©×éºÏÆðÀ´µÄ½á¹¹·½Ê½£¬Ëü³ýÁË·µ»ØÖµÒÔÍ⣬»¹ÐèÒªÒ»¸öÉÏÏÂÎÄ¡£³£¼ûµÄ
Monad ÓмÆËãÈÎÎñ£¬·ÖÖ§ÈÎÎñ£¬»òÕß I/O ²Ù×÷¡£
Èç¹ûûÓжîÍâµÄ¹¦ÄÜ£¬ÎÒÃÇÓÐÈçϹ¦ÄÜ£º
val fetch : commit
-> source
val build : source -> image |
Äú¿ÉÒÔ½«ÆäÀí½âΪ¡°build ÊÇÒ»¸ö»ñȡԴֵ²¢·µ»Ø£¨Docker£©¾µÏñµÄº¯Êý¡±¡£
ÕâЩº¯ÊýºÜÈÝÒ××éºÏÔÚÒ»Æð£¬ÐγÉÒ»¸ö¸ü´óµÄº¯ÊýÀ´»ñÈ¡Ìá½»²¢¹¹½¨Ëü£º
let fab c =
let src = fetch c in
build src |

ÎÒÃÇ»¹¿ÉÒÔ½«ÆäËõ¶ÌΪ build£¨fetch c£©»ò fetch c |>build¡£OCaml
ÖеÄ|>£¨pipe£©ÔËËã·ûÖ»µ÷ÓÃÆäÓÒ²àµÄº¯Êý£¬¶ø²ÎÊýÔÚÆä×ó²à¡£
ΪÁ˽«ÕâЩº¯ÊýÀ©Õ¹Îª²¢·¢µÄ£¬ÎÒÃÇ¿ÉÒÔÈÃËüÃÇ·µ»Ø³Ðŵ£¬ÀýÈ磬
val fetch : commit
-> source promise
val build : source -> image promise |
µ«ÊÇÏÖÔÚÎÒÃÇÎÞ·¨Ê¹Óà let£¨»ò|>£©ÇáËÉ×éºÏËüÃÇ£¬ÒòΪ fetch µÄÊä³öÀàÐÍÓë build
µÄÊäÈ벻ƥÅä¡£
µ«ÊÇ£¬ÎÒÃÇ¿ÉÒÔ¶¨ÒåÒ»¸öÀàËÆµÄ²Ù×÷£¬let£¨»ò>>=£©À´´¦Àí³Ðŵ¡£ËüÁ¢¼´·µ»Ø¶Ô×îÖÕ½á¹ûµÄ³Ðŵ£¬²¢ÔÚµÚÒ»¸ö³ÐŵʵÏÖºóµ÷ÓÃ
let* µÄÖ÷Ìå¡£ÄÇôÎÒÃÇÓУº
let fab c =
let* src = fetch c in
build src |
»»¾ä»°Ëµ£¬Í¨¹ýÔÚÖÜΧÈöÉϼ¸¸öÐǺÅ×Ö·û£¬ÎÒÃÇ¿ÉÒÔ½«¼òµ¥µÄ¾É¹ÜµÀ±ä³ÉÒ»¸öеIJ¢·¢¹ÜµÀ£¡Ê¹Óà let*
±àд promise returning º¯ÊýµÄʱ¼ä¹æÔòÓëʹÓà let ±àд³£¹æº¯ÊýµÄʱ¼ä¹æÔòÍêÈ«Ïàͬ£¬Òò´ËʹÓÃ
promise ±àд³ÌÐòÓë±àд³£¹æ³ÌÐòÒ»Ñù¼òµ¥¡£
½ö½öʹÓà let *²»»áÔÚÎÒÃǵĹܵÀÖÐÌí¼ÓÈκβ¢·¢£¨ËüÖ»ÔÊÐíËüÓëÆäËû´úÂë²¢·¢Ö´ÐУ©¡£µ«ÊÇÎÒÃÇ¿ÉÒÔΪ´Ë¶¨Òå¶îÍâµÄº¯Êý£¬±ÈÈç
all Ò»´Î¼ÆËãÒ»¸öÁбíÖеÄÿ¸ö³Ðŵ£¬»òÕßʹÓà and ÔËËã·ûָʾÁ½¸öÊÂÎïÓ¦¸Ã²¢ÐÐÔËÐУº
³ýÁË´¦Àí³ÐŵÍ⣬ÎÒÃÇ»¹¿ÉÒÔΪ¿ÉÄÜ·µ»Ø´íÎóµÄº¯Êý£¨Ö»ÓÐÔÚµÚÒ»¸öÖµ³É¹¦Ê±²Åµ÷Óà let µÄÖ÷Ì壩»òΪʵʱ¸üУ¨Ã¿´ÎÊäÈë¸ü¸Äʱ¶¼µ÷ÓÃÖ÷Ì壩»òΪËùÓÐÕâЩ¶«Î÷Ò»Æð¶¨Òå
let*¡£ÕâÊǵ¥×ӵĻù±¾¸ÅÄî¡£
ÕâÆäʵºÜ¹ÜÓá£ÔÚ 2016 Ä꣬ÎÒÓÃÕâÖÖ·½·¨×öÁË DataKitCI£¬Ëü×î³õÓÃÓÚ Docker-for-Mac
É쵀 CI ϵͳ¡£Ö®ºó£¬Madhavapeddy ÓÃËü´´½¨ÁË opam-repo-ci£¬ÕâÊÇ opam-repository
É쵀 CI ϵͳ£¬OCaml ÉÏÖ÷ÒªµÄÈí¼þ²Ö¿â¡£Õ⽫¼ì²éÿ¸öÐ嵀 PR ÒԲ鿴ËüÌí¼Ó»òÐÞ¸ÄÁËÄÄЩ°ü£¬Õë¶Ô¶à¸ö
OCaml ±àÒëÆ÷°æ±¾ºÍ Linux ·¢Ðа棨Debian¡¢Ubuntu¡¢Alpine¡¢CentOS¡¢Fedora
ºÍ OpenSUSE£©²âÊÔÿ¸ö°ü£¬È»ºó¸ù¾Ý¸ü¸ÄµÄ°ü²éÕÒËùÓаüµÄËùÓа汾£¬²¢²âÊÔÕâЩ°æ±¾¡£
ʹÓà monad µÄÖ÷ÒªÎÊÌâÊÇÎÒÃDz»ÄܶԹܵÀ½øÐо²Ì¬·ÖÎö¡£¿¼ÂÇÉÏÃæµÄ example2 º¯Êý¡£ÔÚ²éѯ
GitHub ÒÔ»ñµÃ²âÊÔÌύ֮ǰ£¬ÎÒÃÇÎÞ·¨ÔËÐиú¯Êý£¬Òò´Ë²»ÖªµÀËü½«×öʲô¡£Ò»µ©ÎÒÃÇÓÐÁË commit£¬ÎÒÃǾͿÉÒÔµ÷ÓÃ
example2commit£¬µ«ÊÇÔÚ fetch ºÍ docker_pull ²Ù×÷Íê³É֮ǰ£¬ÎÒÃÇÎÞ·¨¼ÆËã
let* µÄÖ÷ÌåÀ´ÕÒ³ö¹ÜµÀ½ÓÏÂÀ´½«×öʲô¡£
»»ÑÔÖ®£¬ÎÒÃÇÖ»ÄÜ»æÖÆÍ¼±í£¬ÏÔʾÒѾִÐлòÕýÔÚÖ´ÐеĹܵÀ룬²¢ÇÒ±ØÐëʹÓÃºÍ * ÊÖ¶¯Ö¸Ê¾²¢·¢µÄ»ú»á¡£
Arrow ·½·¨
Arrow ʹ¹ÜµÀµÄ¾²Ì¬·ÖÎö³ÉΪ¿ÉÄÜ¡£¶ø²»ÊÇÎÒÃǵÄÒ»Ôªº¯Êý£º
val fetch : commit
-> source promise
val build : source -> image promise |
ÎÒÃÇ¿ÉÒÔ¶¨Òå¼ýÍ·ÀàÐÍ£º
type ('a, 'b)
arrow
val fetch : (commit, source) arrow
val build : (source, image) arrow |
a£¨'a£¬'b£©arrow ÊÇÒ»¸ö½ÓÊÜ a ÀàÐÍÊäÈë²¢Éú³É b ÀàÐͽá¹ûµÄ¹ÜµÀ¡£Èç¹ûÎÒÃǶ¨ÒåÀàÐÍ£¨'a£¬'b£©arrow='a->'b
promise£¬ÔòÕâÓëÒ»Ôª°æ±¾Ïàͬ¡£µ«ÊÇ£¬ÎÒÃÇ¿ÉÒÔ½«¼ýÍ·ÀàÐͳéÏ󻯣¬²¢¶ÔÆä½øÐÐÀ©Õ¹£¬ÒÔ´æ´¢ÎÒÃÇÐèÒªµÄÈκξ²Ì¬ÐÅÏ¢¡£ÀýÈ磬ÎÒÃÇ¿ÉÒÔ±ê¼Ç¼ýÍ·£º
type ('a, 'b)
arrow = {
f : 'a -> 'b promise;
label : string;
} |
ÕâÀ¼ýÍ·ÊÇÒ»¸ö¼Ç¼¡£f ÊǾɵÄÒ»Ôªº¯Êý£¬label ÊÇ¡°¾²Ì¬·ÖÎö¡±¡£
Óû§¿´²»µ½ arrow ÀàÐ͵ÄÄÚ²¿£¬±ØÐëʹÓà arrow ʵÏÖÌṩµÄº¯ÊýÀ´¹¹½¨¹ÜµÀ¡£ÓÐÈý¸ö»ù±¾¹¦ÄÜ¿ÉÓãº
val arr : ('a
-> 'b) -> ('a, 'b) arrow
val ( >>> ) : ('a, 'b) arrow -> ('b,
'c) arrow -> ('a, 'c) arrow
val first : ('a, 'b) arrow -> (('a * 'c), ('b
* 'c)) arrow |
arr ½ÓÊÜ´¿º¯Êý²¢¸ø³öµÈ¼ÛµÄ¼ýÍ·¡£¶ÔÓÚÎÒÃǵijÐŵʾÀý£¬ÕâÒâζ׿ýÍ··µ»ØÒѾʵÏֵijÐŵ¡£>>>°ÑÁ½¸ö¼ýÍ·Á¬ÔÚÒ»Æð¡£Ê×ÏÈ´Ó¡°a¡±µ½¡°b¡±È¡Ò»¸ö¼ýÍ·£¬¸ÄΪ³É¶ÔʹÓ᣸öԵĵÚÒ»¸öÔªËØ½«Óɸø¶¨µÄ¼ýÍ·´¦Àí£¬µÚ¶þ¸ö×é¼þ½«Ô·â²»¶¯µØ·µ»Ø¡£
ÎÒÃÇ¿ÉÒÔÈÃÕâЩ²Ù×÷×Ô¶¯´´½¨´øÓÐÊʵ± f ºÍ label ×ֶεÄмýÍ·¡£ÀýÈ磬ÔÚ a>>>b
ÖУ¬½á¹û label ×ֶοÉÒÔÊÇ×Ö·û´®{a.label}>>{b.label}¡£ÕâÒâζ×ÅÎÒÃÇ¿ÉÒÔÏÔʾ¹ÜµÀ£¬¶ø²»±ØÏÈÔËÐÐËü£¬Èç¹ûÐèÒªµÄ»°£¬ÎÒÃÇ¿ÉÒÔºÜÈÝÒ×µØÓøü½á¹¹»¯µÄÄÚÈÝÌæ»»
label¡£
ÎÒÃǵĵÚÒ»¸öÀý×ÓÊÇ£º
let example1
commit =
let src = fetch commit in
let image = build src in
test image |
to
let example1
=
fetch >>> build >>> test |
ËäÈ»ÎÒÃDz»µÃ²»·ÅÆú±äÁ¿Ãû£¬µ«ÕâËÆºõºÜÁîÈËÓä¿ì¡£µ«ÊÂÇ鿪ʼ±äµÃ¸´ÔÓ£¬ÓÐÁ˸ü´óµÄÀý×Ó¡£ÀýÈç
2£¬ÎÒÃÇÐèÒª¶¨Ò弸¸ö±ê×¼×éºÏ£º
(** Process the
second component of a tuple, leaving the first
unchanged. *)
let second f =
let swap (x, y) = (y, x) in
arr swap >>> first f >>> arr
swap
(** [f *** g] processes the first component of
a pair with [f] and the second
with [g]. *)
let ( *** ) f g =
first f >>> second g
(** [f &&& g] processes a single value
with [f] and [g] in parallel and
returns a pair with the results. *)
let ( &&& ) f g =
arr (fun x -> (x, x)) >>> (f *** g) |
Then, example2 changes from:
let example2
commit =
let src = fetch commit in
let base = docker_pull "ocaml/opam2"
in
let build ocaml_version =
let dockerfile = make_dockerfile ~base ~ocaml_version
in
let image = build ~dockerfile src ~label:ocaml_version
in
test image
in
build "4.07";
build "4.08" |
to:
let example2
=
let build ocaml_version =
first (arr (fun base -> make_dockerfile ~base
~ocaml_version)) >>> build_with_dockerfile
~label:ocaml_version >>> test
in
arr (fun c -> ((), c)) >>> (docker_pull
"ocaml/opam2" *** fetch) >>>
(build "4.07" &&& build
"4.08")
>>> arr (fun ((), ()) -> ()) |
ÎÒÃÇÒѾ¶ªÊ§ÁË´ó¶àÊý±äÁ¿Ãû£¬¶ø²»µÃ²»Ê¹ÓÃÔª×飬¼ÇסÎÒÃǵÄÖµÔÚÄÄÀï¡£ÕâÀïÓÐÁ½¸öÖµ²¢²»ÊǺÜÔã¸â£¬µ«ÊÇËæ×Ÿü¶àµÄÖµ±»Ìí¼Ó²¢ÇÒÎÒÃÇ¿ªÊ¼Ç¶Ì×Ôª×飬Ëü±äµÃ·Ç³£À§ÄÑ¡£ÎÒÃÇ»¹Ê§È¥ÁËÔÚ
build~dockerfile src ÖÐʹÓÿÉÑ¡±ê¼Ç²ÎÊýµÄÄÜÁ¦£¬¶øÊÇÐèҪʹÓÃÒ»¸öвÙ×÷£¬¸Ã²Ù×÷½ÓÊÜ
dockerfile ºÍÔ´µÄÔª×é¡£
¼ÙÉèÏÖÔÚÔËÐвâÊÔÐèÒª´ÓÔ´´úÂë»ñÈ¡²âÊÔÓÃÀý¡£ÔÚÔʼ´úÂëÖУ¬ÎÒÃÇÖ»ÐèʹÓãºsrc ½«²âÊÔͼÏñ¸ü¸ÄΪ²âÊÔͼÏñ¡£ÔÚ
arrow °æ±¾ÖУ¬ÎÒÃÇÐèÒªÔÚÉú³É²½Öè֮ǰ¸´ÖÆÔ´´úÂ룬ʹÓôø dockerfile µÄ first
build_ ÔËÐÐÉú³É£¬²¢È·±£²ÎÊýÊÇвâÊÔʹÓõÄÕýÈ··½·¨¡£
Dart ·½·¨
ÎÒ¿ªÊ¼»³ÒÉÊÇ·ñÓÐÒ»ÖÖ¸ü¼òµ¥µÄ·½·¨À´ÊµÏÖÓë¼ýÍ·ÏàͬµÄ¾²Ì¬·ÖÎö£¬µ«ÊÇûÓÐÎÞµãÓï·¨£¬¶øÇÒËÆºõÓС£¿¼ÂÇʾÀý
1 µÄÒ»Ôª°æ±¾¡£ÎÒÃÇÓУº
val build : source
-> image promise
val test : image -> results promise
let example1 commit =
let* src = fetch commit in
let* image = build src in
test image |
Èç¹ûÄã²»ÖªµÀÃÉÄÈ×ȵÄÊ£¬Ä㻹ÓбðµÄ°ì·¨¡£Äú¿ÉÒÔ¶¨Òå build ºÍ
test£¬½« promises ×÷ΪÊäÈ룬¶ø²»ÊÇʹÓà let* µÈ´ý»ñÈ¡Íê³É£¬È»ºóʹÓÃÔ´µ÷Óà build£º
val build : source
promise -> image promise
val test : image promise -> results promise |
±Ï¾¹£¬fetching ¸øÁËÄãÒ»¸öÔ´´úÂë³Ðŵ£¬ÄãÏëÒªÒ»¸öͼÏñ³Ðŵ£¬ËùÒÔÕâ¿´ÆðÀ´ºÜ×ÔÈ»¡£ÎÒÃÇÉõÖÁ¿ÉÒÔÒÔ³ÐŵΪÀý¡£È»ºó¿´ÆðÀ´ÊÇÕâÑùµÄ£º
let example1
commit =
let src = fetch commit in
let image = build src in
test image |
ºÜºÃ£¬ÒòΪËüºÍÎÒÃǸտªÊ¼µÄ¼òµ¥°æ±¾ÊÇÒ»ÑùµÄ¡£ÎÊÌâÊÇЧÂʵÍÏ£º
ÎÒÃÇÓóÐŵµÄ·½Ê½µ÷Óà example1£¨ÎÒÃÇ»¹²»ÖªµÀËüÊÇʲô£©¡£
ÎÒÃDz»±ØµÈ´ýÕÒ³öÒª²âÊÔµÄÌá½»£¬¶øÊǵ÷Óà fetch£¬»ñȡij¸öÔ´µÄ³Ðŵ¡£
²»ÐèÒªµÈ´ý»ñȡԴ´úÂ룬ÎÒÃǾ͵÷Óà build£¬»ñȡͼÏñµÄ³Ðŵ¡£
²»Óõȴý¹¹½¨£¬ÎÒÃǵ÷Óà test£¬µÃµ½½á¹ûµÄ³Ðŵ¡£
ÎÒÃÇÁ¢¼´·µ»Ø²âÊÔ½á¹ûµÄ×îÖÕ³Ðŵ£¬µ«ÎÒÃÇ»¹Ã»ÓÐ×öÈκÎÕæÕýµÄ¹¤×÷¡£Ïà·´£¬ÎÒÃǽ¨Á¢ÁËÒ»³¤´®µÄ³Ðŵ£¬ÀË·ÑÁ˼ÇÒä¡£
µ«ÊÇ£¬ÔÚÕâÖÖÇé¿öÏ£¬ÎÒÃÇÏ£ÍûÖ´Ðо²Ì¬·ÖÎö¡£i¡¢ ÎÒÃÇÏëÔÚÄÚ´æÖн¨Á¢Ò»Ð©±íʾÁ÷Ë®ÏßµÄÊý¾Ý½á¹¹¡¡ÕâÕýÊÇÎÒÃǶÔ
monad µÄ¡°µÍЧ¡±Ê¹ÓÃËù²úÉúµÄ½á¹û£¡
ΪÁËʹÆäÓÐÓã¬ÎÒÃÇÐèÒª»ù±¾²Ù×÷£¨±ÈÈç fetch£©À´Îª¾²Ì¬·ÖÎöÌṩһЩÐÅÏ¢£¨±ÈÈç±êÇ©£©¡£OCaml
µÄ let Ó﷨ûÓÐΪ±êÇ©ÌṩÃ÷ÏÔµÄλÖ㬵«ÊÇÎÒÄܹ»¶¨ÒåÒ»¸öÔËËã·û£¨let**£©£¬¸ÃÔËËã·û·µ»ØÒ»¸ö½ÓÊÜ
label ²ÎÊýµÄº¯Êý¡£Ëü¿ÉÓÃÓÚÉú³ÉÈçÏ»ù±¾²Ù×÷£º
let fetch commit
= "fetch" |>
let** commit = commit in
(* (standard monadic implementation of fetch goes
here) *) |
Òò´Ë£¬fetch ½ÓÊÜÒ»¸öÌá½»µÄ³Ðŵ£¬¶ÔËüÖ´ÐÐÒ»¸öµ¥×Ö½Ú°ó¶¨ÒԵȴýʵ¼ÊµÄÌá½»£¬È»ºóÏñÒÔǰһÑù¼ÌÐø£¬µ«Ëü½«°ó¶¨±ê¼ÇΪһ¸ö
fetch ²Ù×÷¡£Èç¹û fetch °üº¬¶à¸ö²ÎÊý£¬Ôò¿ÉÒÔʹÓà and* ²¢ÐеȴýËùÓвÎÊý¡£
ÀíÂÛÉÏ£¬let**In fetch µÄÖ÷Ìå¿ÉÒÔ°üº¬½øÒ»²½µÄ°ó¶¨¡£Èç¹ûÄÇÑùµÄ»°£¬ÎÒÃÇÔÚÒ»¿ªÊ¼¾ÍÎÞ·¨·ÖÎöÕû¸ö¹ÜµÀ¡£µ«ÊÇ£¬Ö»ÒªÔÓïÔÚ¿ªÊ¼Ê±µÈ´ýËùÓÐÊäÈ룬²¢ÇÒ²»ÔÚÄÚ²¿½øÐÐÈκΰ󶨣¬ÎÒÃǾͿÉÒÔ¾²Ì¬µØ·¢ÏÖÕû¸ö¹ÜµÀ¡£
ÎÒÃÇ¿ÉÒÔÑ¡ÔñÊÇ·ñ½«ÕâЩ°ó¶¨²Ù×÷¹«¿ª¸øÓ¦ÓóÌÐò´úÂë¡£Èç¹û let*£¨»ò let**£©±»¹«¿ª£¬ÄÇôӦÓóÌÐò¾Í¿ÉÒÔʹÓÃ
monad µÄËùÓбí´ïÄÜÁ¦£¬µ«ÊÇÔÚijЩ³Ðŵ½â¾ö֮ǰ£¬ÎÒÃǽ«ÎÞ·¨ÏÔʾÕû¸ö¹ÜµÀ¡£Èç¹ûÎÒÃÇÒþ²ØËüÃÇ£¬ÄÇôӦÓóÌÐòÖ»ÄÜÉú³É¾²Ì¬¹ÜµÀ¡£
µ½Ä¿Ç°ÎªÖ¹£¬Îҵķ½·¨ÊÇʹÓà let* ×÷ΪÌÓÉú²Õ¿Ú£¬ÕâÑù¾Í¿ÉÒÔ½¨ÔìÈκÎËùÐèµÄ¹ÜµÀ£¬µ«ÎÒºóÀ´ÓøüרҵµÄ²Ù×÷À´´úÌæËüµÄÈκÎÓÃ;¡£ÀýÈ磬ÎÒÌí¼ÓÁË£º
val list_map
: ('a t -> 'b t) -> 'a list t -> 'b list
t |
Õ⽫´¦ÀíÔËÐÐʱ²ÅÖªµÀµÄÁбíÖеÄÿ¸öÏȻ¶ø£¬ÎÒÃÇÈÔÈ»¿ÉÒÔ¾²Ì¬µØÖªµÀÎÒÃǽ«Ó¦ÓÃÓÚÿ¸öÏîµÄ¹ÜµÀ£¬¼´Ê¹ÎÒÃDz»ÖªµÀÏî±¾ÉíÊÇʲô¡£list_map
±¾À´¿ÉÒÔʹÓà let* ʵÏÖ£¬µ«ÕâÑùÎÒÃǾÍÎÞ·¨¾²Ì¬µØ¿´µ½¹ÜµÀ¡£
ÏÂÃæÊÇÁíÍâÁ½¸öʹÓà dart ·½·¨µÄʾÀý£º
let example2
commit =
let src = fetch commit in
let base = docker_pull "ocaml/opam2"
in
let build ocaml_version =
let dockerfile =
let+ base = base in
make_dockerfile ~base ~ocaml_version in
let image = build ~dockerfile src ~label:ocaml_version
in
test image
in
all [
build "4.07";
build "4.08"
] |
ÓëÔÀ´Ïà±È£¬ÎÒÃÇÓÐÒ»¸ö all À´ºÏ²¢½á¹û£¬²¢ÇÒÔÚ¼ÆËã dockerfile
ʱÓÐÒ»¸ö¶îÍâµÄ let+base=base¡£let+ Ö»ÊÇ map µÄÁíÒ»ÖÖÓï·¨£¬ÔÚÕâÀïʹÓã¬ÒòΪÎÒÑ¡Ôñ²»¸ü¸Ä
make_dockerfile µÄÇ©Ãû¡£»òÕߣ¬ÎÒÃÇ¿ÉÒÔÈÃÄãµÄ dockerfile ½ÓÊÜÒ»¸ö»ù±¾Í¼ÏñµÄ³Ðŵ£¬²¢ÔÚÀïÃæ×öµØÍ¼¡£ÒòΪ
map ÐèÒªÒ»¸ö´¿ÊµÌ壨make_dockerfile Ö»Éú³ÉÒ»¸ö×Ö·û´®£»Ã»ÓгÐŵ»ò´íÎ󣩣¬ËùÒÔËü²»ÐèÒªÔÚͼ±íÉÏÓÐ×Ô¼ºµÄ¿ò£¬²¢ÇÒÎÒÃDz»»áÒòΪÔÊÐíʹÓÃËü¶ø¶ªÊ§Èκζ«Î÷¡£
let example3
commit =
let src = fetch commit in
let image = build src in
let ok = test image in
let revdeps = get_revdeps src in
gate revdeps ~on:ok |>
list_iter ~pp:Fmt.string example1 |
ÕâÏÔʾÁËÁíÒ»¸ö×Ô¶¨Òå²Ù×÷£ºgate revdeps~on:ok ÊÇÒ»¸ö³Ðŵ£¬Ö»ÓÐÔÚ revdeps
ºÍ ok ¶¼½â¾öºó²ÅÄܽâ¾ö¡£Õ⽫×èÖ¹ËüÔÚ¿â×Ô¼ºµÄ²âÊÔͨ¹ý֮ǰ²âÊÔ¿âµÄ revdeps£¬¼´Ê¹Èç¹ûÎÒÃÇÏ£ÍûËü¿ÉÒÔ²¢ÐеØÕâÑù×ö¡£¶ø¶ÔÓÚ
monad£¬ÎÒÃDZØÐëÔÚÐèÒªµÄµØ·½ÏÔʽµØÆôÓò¢·¢£¨Ê¹ÓÃºÍ *£©£¬¶ø¶ÔÓÚ dart£¬ÎÒÃDZØÐëÔÚ²»ÐèÒªµÄµØ·½ÏÔʽµØ½ûÓò¢·¢£¨Ê¹ÓÃ
gate£©¡£
ÎÒ»¹Ìí¼ÓÁËÒ»¸ö list-iter ±ãÀûº¯Êý£¬²¢ÎªËüÌṩÁËÒ»¸öƯÁÁµÄ printer ²ÎÊý£¬ÕâÑùÒ»µ©ÖªµÀÁбíÊäÈ룬ÎÒÃǾͿÉÒÔÔÚͼ±íÖбê¼Ç°¸Àý¡£
×îºó£¬ËäÈ»ÎÒ˵¹ý²»ÄÜÔÚÔÓïÖÐʹÓà let*£¬µ«ÈÔÈ»¿ÉÒÔʹÓÃÆäËûһЩ monad£¨Ëü²»»áÉú³Éͼ£©¡£Êµ¼ÊÉÏ£¬ÔÚʵ¼ÊϵͳÖУ¬ÎÒ¶ÔÔÓïʹÓÃÁËÒ»¸öµ¥¶ÀµÄ
let>²Ù×÷·û¡£Õâ¾ÍÒªÇóÖ÷ÌåʹÓõײã promise ¿âÌṩµÄ·ÇͼÉú³É³Ðŵ£¬Òò´Ë²»ÄÜÔÚÔÓïµÄÖ÷ÌåÖÐʹÓÃ
let*£¨»ò let>£©¡£
ºÍ Arrow ½øÐбȽÏ
¸ø¶¨Ò»¸ö¡°dart¡±£¬Äú¿ÉÒÔͨ¹ý¶¨ÒåÀýÈç¡£
type ('a, 'b)
arrow = 'a promise -> 'b promise |
ÄÇô arr ¾ÍÊÇ map£¬f>>>g ¾ÍÊÇÓÐȤµÄ x->g£¨fx£©¡£µÚÒ»¸öÒ²¿ÉÒÔºÜÈÝÒ׵ض¨Ò壬¼ÙÉèÄãÓÐijÖÖº¯ÊýÀ´²¢ÐеØ×öÁ½¼þÊ£¨±ÈÈçÉÏÃæµÄºÍÎÒÃǵģ©¡£
Òò´Ë£¬dart API£¨¼´Ê¹ÓÐ let*hidden£©ÈÔÈ»×ãÒÔ±íʾÈκοÉÒÔʹÓüýÍ· API ±íʾµÄ¹ÜµÀ¡£
Haskell ¼ýÍ·½Ì³Ì ʹÓÃÒ»¸ö¼ýÍ·ÊÇÓÐ״̬º¯ÊýµÄʾÀý¡£ÀýÈ磬ÓÐÒ»¸ö total ¼ýÍ·£¬Ëü·µ»ØËüµÄÊäÈëºÍÒÔǰµ÷ÓÃËüµÄÿ¸öÊäÈëµÄ×ܺ͡£e¡¢
g. ÓÃÊäÈë 1 2 3 µ÷ÓÃÈý´Î£¬²úÉúÊä³ö 1 3 6¡£¶ÔÊäÈëÐòÁÐÔËÐйܵÀ½«·µ»ØÊä³öÐòÁС£
±¾½Ì³ÌʹÓà total ¶¨Òå mean1 º¯Êý£¬ÈçÏÂËùʾ£º
mean1 = (total
&&& (arr (const 1) >>> total))
>>> arr (uncurry (/)) |
Òò´Ë£¬´Ë¹ÜµÀ¸´ÖÆÃ¿¸öÊäÈë±àºÅ£¬½«µÚ¶þ¸ö±àºÅÌæ»»Îª 1£¬½«Á½¸öÁ÷Ïà¼Ó£¬È»ºóÓÃÆä±ÈÂÊÌæ»»Ã¿¶Ô¡£Ã¿´Î½«ÁíÒ»¸öÊý×Ö·ÅÈë¹ÜµÀʱ£¬¶¼»áµÃµ½Æù½ñΪֹÊäÈëµÄËùÓÐÖµµÄƽ¾ùÖµ¡£
ʹÓà dart ÑùʽµÄµÈЧ´úÂëÊÇ£¨OCaml ʹÓà /¡£¶ÔÓÚ¸¡µã³ý·¨£©£º
let mean values
=
let t = total values in
let n = total (const 1.0) in
map (uncurry (/.)) (pair t n) |
Õâ¶ÔÎÒÀ´Ëµ¸üÈÝÒ×Àí½â¡£Í¨¹ý¶¨Òå±ê×¼ÔËËã·û let+£¨¶ÔÓÚ map£©ºÍ
+£¨¶ÔÓÚ pair£©£¬ÎÒÃÇ¿ÉÒÔÉÔ΢¼ò»¯´úÂ룺
let (let+) x
f = map f x
let (and+) = pair
let mean values =
let+ t = total values
and+ n = total (const 1.0) in
t /. n |
ÎÞÂÛÈçºÎ£¬Õâ²»ÊÇÒ»¸öºÜºÃµÄ¼ýͷʾÀý£¬ÒòΪÎÒÃDz»Ê¹ÓÃÒ»¸ö״̬º¯ÊýµÄÊä³ö×÷ΪÁíÒ»¸ö״̬º¯ÊýµÄÊäÈ룬ËùÒÔÕâʵ¼ÊÉÏÖ»ÊÇÒ»¸ö¼òµ¥µÄ
applicative.
²»¹ý£¬ÎÒÃÇ¿ÉÒÔºÜÈÝÒ×µØÓÃÁíÒ»¸öÓÐ״̬º¯ÊýÀ©Õ¹Ê¾Àý¹ÜµÀ£¬Ò²Ðí¿ÉÒÔÌí¼ÓһЩƽ»¬´¦Àí¡£Õâ¿´ÆðÀ´Ïñ¼ýÍ··ûºÅÖеÄ
mean1>>>ƽ»¬£¬Ê¡µÀ·ûºÅÖеÄÖµ|>ƽ¾ùÖµ|>ƽ»¬£¨»òƽ»¬£¨Æ½¾ùÖµ£©£©¡£
×¢Ò⣺Haskell »¹ÓÐÒ»¸ö Arrows Óï·¨À©Õ¹£¬ËüÔÊÐí Haskell
´úÂë±àдΪ£º
mean2 = proc
value -> do
t <- total -< value
n <- total -< 1
returnA -< t / n |
Õâ¸üÏñÊÇ·ÉïÚ·ûºÅ¡£
¸ü¶àʾÀý
ÎÒÔÚ ocurrent/ocurrent ÉϽ¨Á¢ÁËÒ»¸öʹÓÃÕâЩ˼ÏëµÄÉÔ΢À©Õ¹°æ±¾µÄ¿â¡£×ÓĿ¼ lib_term
ÊÇÓëÕâÆª²©¿ÍÎÄÕÂÏà¹ØµÄ²¿·Ö£¬ÔÚ TERM ÖÐÃèÊöÁ˸÷ÖÖ×éºÏ´Ê¡£
ÆäËûĿ¼´¦Àí¸ü¾ßÌåµÄϸ½Ú£¬ÀýÈçÓë Lwt promise ¿âµÄ¼¯³É£¬Ìṩ¹ÜÀí web UI »ò Cap¡¯n
Proto RPC ½Ó¿Ú£¬ÒÔ¼°´øÓÐÓÃÓÚʹÓà Git¡¢GitHub¡¢Docker ºÍ Slack µÄÔÓïµÄ²å¼þ¡£
OCaml Docker »ù´¡¾µÏñ¹¹½¨
ocurrent/docker-base-images °üº¬Ò»¸ö¹ÜµÀ£¬ÓÃÓÚΪ¸÷ÖÖ
Linux ·¢Ðа桢CPU ¼Ü¹¹¡¢OCaml ±àÒëÆ÷°æ±¾ºÍÅäÖÃÑ¡Ïî¹¹½¨ OCaml µÄ Docker
»ù±¾Ó³Ïñ¡£ÀýÈ磬ҪÔÚ Debian 10 ÉϲâÊÔ OCAML4.09£¬¿ÉÒÔÖ´ÐÐÒÔϲÙ×÷£º
$ docker run
--rm -it ocurrent/opam:debian-10-ocaml-4.09
:~$ ocamlopt --version
4.09.0
:~$ opam depext -i utop
[...]
:~$ utop
----+--------+------------------
| Welcome to utop version 2.4.2 (using OCaml version
4.09.0)! |
+---------------------------+
Type #utop_help for help about using utop.
-( 11:50:06 )-< command 0 > -------------{
counter: 0 }-
utop #
|
ÒÔÏÂÊǹܵÀµÄÍâ¹Û£¨µ¥»÷¿É²é¿´ÍêÕû³ß´ç£©

ËüÿÖÜÌáÈ¡ opam ´æ´¢¿âµÄ×îРGit Ìá½»£¬È»ºóΪÿ¸ö·¢Ðа湹½¨°üº¬¸ÃÄÚÈݵĻù±¾Ó³ÏñºÍ opam
°ü¹ÜÀíÆ÷£¬È»ºóΪÿ¸öÊÜÖ§³ÖµÄ±àÒëÆ÷±äÌå¹¹½¨Ò»¸öÓ³Ïñ¡£Ðí¶àͼƬÊǽ¨Á¢ÔÚ¶à¸ö¼Ü¹¹£¨amd64¡¢arm32¡¢arm64
ºÍ ppc64£©Éϵ쬲¢±»ÍƵ½ Docker Hub µÄÒ»¸öÔÝ´æÇø¡£È»ºó£¬¹ÜµÀ½«ËùÓÐÉ¢ÁÐ×éºÏÆðÀ´£¬½«Ò»¸ö¶à¼Ü¹¹Çåµ¥ÍÆË͵½
Docker Hub¡£»¹ÓÐһЩ±ðÃû£¨ÀýÈ磬debian ±íʾ debian-10-ocaml-4.09£©¡£×îºó£¬Èç¹ûÓÐÈκÎÎÊÌ⣬Ôò¹ÜµÀ»á½«´íÎó·¢Ë͵½ËɳÚͨµÀ¡£
Äú¿ÉÄÜÏëÖªµÀ£¬ÎÒÃÇÊÇ·ñÕæµÄÐèÒªÒ»¸ö¹ÜµÀÀ´ÊµÏÖÕâÒ»µã£¬¶ø²»ÊÇ´Ó cron ×÷ÒµÔËÐÐÒ»¸ö¼òµ¥µÄ½Å±¾¡£µ«ÊÇÓµÓÐÒ»¸ö¹ÜµÀ¿ÉÒÔÈÃÎÒÃÇÔÚÔËÐÐËü֮ǰ¿´µ½¹ÜµÀ½«Òª×öʲô£¬¹Û²ì¹ÜµÀµÄ½ø¶È£¬µ¥¶ÀÖØÐÂÆô¶¯Ê§°ÜµÄ×÷Òµ£¬µÈµÈ£¬¼¸ºõÓëÎÒÃDZàдµÄ´úÂëÏàͬ¡£
Èç¹ûÄãÏë¿´Íê³ÉµÄÁ÷Ë®Ïߣ¬¿ÉÒÔÔĶÁ pipeline.ml¡£
OCaml CI
ocurrent/ocaml-ci ÊÇÒ»¸öÓÃÓÚ²âÊÔ OCaml ÏîÄ¿µÄ£¨ÊµÑéÐԵģ©GitHub Ó¦ÓóÌÐò¡£¹ÜµÀ»ñȡӦÓóÌÐòµÄ°²×°ÁÐ±í£¬»ñȡÿ¸ö°²×°µÄÒÑÅäÖô洢¿â£¬»ñȡÿ¸ö´æ´¢¿âµÄ·ÖÖ§ºÍ
PRs£¬È»ºóÕë¶Ô¶à¸ö Linux ·¢ÐаæºÍ OCaml ±àÒëÆ÷°æ±¾²âÊÔÿ¸ö´æ´¢¿âµÄÍ·²¿¡£Èç¹ûÏîĿʹÓÃ
ocamlformat£¬Ëü»¹»á¼ì²éÌá½»µÄ¸ñʽÊÇ·ñÓë ocamlformat µÄ¸ñʽÍêÈ«Ïàͬ¡£

½á¹û×÷ΪÌύ״̬±»Íƻص½ GitHub£¬²¢¼Ç¼ÔÚ web ºÍ tty ui µÄ±¾µØË÷ÒýÖС£ÕâÀïÓкܶàºìÉ«£¬Ö÷ÒªÊÇÒòΪÈç¹ûÒ»¸öÏîÄ¿²»Ö§³ÖÌØ¶¨°æ±¾µÄ
OCaml£¬ÄÇô¹¹½¨»á±»±ê¼ÇΪʧ°Ü£¬²¢ÔڹܵÀÖÐÏÔʾΪºìÉ«£¬¾¡¹ÜÔÚÉú³É GitHub ״̬±¨¸æÊ±»á¹ýÂ˵ôÕâЩʧ°Ü¡£ÎÒÃÇ¿ÉÄÜÐèÒªÒ»¸öеÄÑÕÉ«Ìø¹ý½×¶Î¡£
½áÂÛ
±àд CI/CD ¹ÜµÀºÜ·½±ã£¬¾ÍºÃÏñËüÃÇÊÇÒ»´ÎÁ¬ÐøÔËÐÐÕâЩ²½Ö貢ʼÖճɹ¦µÄµ¥µã½Å±¾Ò»Ñù£¬È»ºóÖ»ÒªÉÔ×÷¸ü¸Ä£¬¹ÜµÀ¾Í»áÔÚÊäÈë¸ü¸ÄʱÔËÐÐÕâЩ²½Ö裬ͬʱÌṩÈÕÖ¾¼Ç¼¡¢´íÎ󱨸桢ȡÏûºÍÖØ½¨Ö§³Ö¡£
ʹÓà monad ¿ÉÒÔºÜÈÝÒ׵ؽ«ÈκγÌÐòת»»Îª¾ßÓÐÕâÐ©ÌØÐԵijÌÐò£¬µ«ÊÇ£¬Óë³£¹æ³ÌÐòÒ»Ñù£¬ÔÚÔËÐÐijЩÊý¾Ý֮ǰ£¬ÎÒÃDz»ÖªµÀ¸Ã³ÌÐò½«ÈçºÎ´¦ÀíÕâЩÊý¾Ý¡£ÌرðÊÇ£¬ÎÒÃÇÖ»ÄÜ×Ô¶¯Éú³ÉÏÔʾÒѾ¿ªÊ¼µÄ²½ÖèµÄͼ±í¡£
´«Í³µÄ¾²Ì¬·ÖÎö·½·¨ÊÇʹÓüýÍ·¡£Õâ±Èµ¥Ôª¸ñÉÔ΢ÓÐÏÞ£¬ÒòΪÁ÷Ë®ÏߵĽṹ²»Äܸù¾ÝÊäÈëÊý¾Ý¶ø¸Ä±ä£¬¾¡¹ÜÎÒÃÇ¿ÉÒÔÔö¼ÓÓÐÏÞµÄÁé»îÐÔ£¬ÀýÈç¿ÉÑ¡µÄ²½Öè»òÁ½¸ö·ÖÖ§Ö®¼äµÄÑ¡Ôñ¡£µ«ÊÇ£¬Ê¹ÓüýÍ··ûºÅ±àд¹ÜµÀÊǺÜÀ§Äѵģ¬ÒòΪÎÒÃDZØÐëʹÓÃÎÞµãÑùʽ£¨Ã»ÓбäÁ¿£©±à³Ì¡£
ͨ¹ýÒÔÒ»ÖÖ²»Ñ°³£µÄ·½Ê½Ê¹Óà monad£¨ÕâÀï³ÆÎª¡°dart¡±£©£¬ÎÒÃÇ¿ÉÒÔ»ñµÃ¾²Ì¬·ÖÎöµÄÏàͬºÃ´¦¡£ÎÒÃǵĺ¯Êý²»ÊǽÓÊÜ´¿Öµ²¢·µ»Ø°ü×°ÖµµÄº¯Êý£¬¶øÊǽÓÊܲ¢·µ»Ø°ü×°Öµ¡£Õâµ¼ÖÂÓï·¨¿´ÆðÀ´ÓëÆÕͨ±à³ÌÏàͬ£¬µ«ÔÊÐí¾²Ì¬·ÖÎö£¨´ú¼ÛÊÇÎÞ·¨Ö±½Ó²Ù×÷°ü×°µÄÖµ£©¡£
Èç¹ûÎÒÃÇÒþ²Ø£¨»ò²»Ê¹Óã©monad µÄ let*£¨bind£©º¯Êý£¬ÄÇôÎÒÃÇ´´½¨µÄ¹ÜµÀ×ÜÊÇ¿ÉÒÔ¾²Ì¬µØÈ·¶¨µÄ¡£Èç¹ûÎÒÃÇʹÓð󶨣¬ÄÇô¹ÜµÀÖлáÓÐËæ×ŹܵÀÔËÐжøÀ©Õ¹µ½¸ü¶à¹ÜµÀ½×¶ÎµÄ¿×¡£
»ù±¾²½Öè¿ÉÒÔͨ¹ýʹÓõ¥¸ö¡°±êÇ©°ó¶¨¡±´´½¨£¬ÆäÖбêǩΪÔ×Ó×é¼þÌṩ¾²Ì¬·ÖÎö¡£
ÎÒÒÔǰ´Óδ¼û¹ýʹÓùýÕâÖÖģʽ£¨»òÕßÔÚ arrow ÎĵµÖÐÌáµ½¹ý£©£¬ËüËÆºõÌṩÁËÓë arrow ÍêÈ«ÏàͬµÄºÃ´¦£¬¶øÇÒÄѶÈҪСµÃ¶à¡£Èç¹ûÕâ¸öÃû×ÖÊÇÕæµÄ£¬¸æËßÎÒ£¡
ÕâÏ×÷ÓÉ OCaml ʵÑéÊÒ×ÊÖú¡£ |