මෑතකදී හස්කල් දෙස කෙටියෙන් බැලූ විට, කෙටියෙන්, සාරාංශගත, ප්රායෝගික වනු ඇත්තේ කුමක්ද මොනාඩ් යනු කුමක්ද පැහැදිලි කිරීමක් වනු ඇත්තේ කුමක් ද?
මට හමු වී ඇති බොහෝ පැහැදිලි කිරීම් තරමක් ප්රවේශ විය නොහැකි සහ ප්රායෝගික විස්තර නොමැති බව මට පෙනී ගොස් ඇත.
මෑතකදී හස්කල් දෙස කෙටියෙන් බැලූ විට, කෙටියෙන්, සාරාංශගත, ප්රායෝගික වනු ඇත්තේ කුමක්ද මොනාඩ් යනු කුමක්ද පැහැදිලි කිරීමක් වනු ඇත්තේ කුමක් ද?
මට හමු වී ඇති බොහෝ පැහැදිලි කිරීම් තරමක් ප්රවේශ විය නොහැකි සහ ප්රායෝගික විස්තර නොමැති බව මට පෙනී ගොස් ඇත.
Answers:
පළමුවැන්න: ඔබ ගණිත ian යෙකු නොවේ නම් මොනාඩ් යන පදය ටිකක් හිස් ය. විකල්ප යෙදුමක් වන්නේ ගණනය කිරීම් සාදන්නා වන අතර එය සැබවින්ම ප්රයෝජනවත් වන්නේ කුමක් ද යන්න පිළිබඳ විස්තරයකි.
ඔබ ප්රායෝගික උදාහරණ ඉල්ලයි:
උදාහරණ 1: ලැයිස්තු අවබෝධය :
[x*2 | x<-[1..10], odd x]
මෙම ප්රකාශනය 1 සිට 10 දක්වා පරාසයක ඇති සියලුම අමුතු සංඛ්යා දෙගුණ කරයි. ඉතා ප්රයෝජනවත්!
ලැයිස්තු මොනාඩ් හි සමහර මෙහෙයුම් සඳහා මෙය සැබවින්ම සින්ටැක්ටික් සීනි බව පෙනේ. එකම ලැයිස්තු අවබෝධය මෙසේ ලිවිය හැකිය:
do
x <- [1..10]
guard (odd x)
return (x * 2)
හෝ පවා:
[1..10] >>= (\x -> guard (odd x) >> return (x*2))
උදාහරණ 2: ආදානය / ප්රතිදානය :
do
putStrLn "What is your name?"
name <- getLine
putStrLn ("Welcome, " ++ name ++ "!")
මෙම උදාහරණ දෙකම මොනාඩ්ස්, AKA ගණනය කිරීම් සාදන්නන් භාවිතා කරයි. පොදු තේමාව වන්නේ මොනාඩ් දාමයන් යම් නිශ්චිත, ප්රයෝජනවත් ආකාරයකින් ක්රියාත්මක කිරීමයි. ලැයිස්තු අවබෝධය තුළ, මෙහෙයුම් දම්වැල් කර ඇති අතර එමඟින් මෙහෙයුමක් ලැයිස්තුවක් ලබා දෙන්නේ නම්, සෑම අයිතමයකම පහත සඳහන් මෙහෙයුම් සිදු කරනු ලැබේ . අනෙක් අතට IO මොනාඩ් විසින් අනුක්රමිකව මෙහෙයුම් සිදු කරයි, නමුත් "ලෝකයේ තත්වය" නිරූපණය කරන "සැඟවුණු විචල්යයක්" පසුකර යන අතර එමඟින් I / O කේතය පිරිසිදු ක්රියාකාරී ආකාරයකින් ලිවීමට අපට ඉඩ සලසයි.
දම්වැල් මෙහෙයුම් වල රටාව බෙහෙවින් ප්රයෝජනවත් වන අතර එය හස්කල් හි විවිධ දේ සඳහා භාවිතා කරයි.
තවත් උදාහරණයක් වන්නේ ව්යතිරේකයන් ය: Error
මොනාඩ් භාවිතා කරමින් මෙහෙයුම් දම්වැල් කර ඇති අතර ඒවා අනුක්රමිකව සිදු කරනු ලැබේ, දෝෂයක් විසි වුවහොත් හැර, අනෙක් දාමය අතහැර දමනු ලැබේ.
ලැයිස්තු-අවබෝධ කර ගැනීමේ සින්ටැක්ස් සහ කළ යුතු අංකනය යන දෙකම >>=
ක්රියාකරු භාවිතා කරමින් දම්වැල් මෙහෙයුම් සඳහා සින්ටැක්ටික් සීනි වේ. මොනාඩ් යනු මූලික වශයෙන් >>=
ක්රියාකරුට සහාය දක්වන වර්ගයකි .
උදාහරණ 3: විග්රහකය
මෙය ඉතා සරල විග්රහයක් වන අතර එය උපුටා ගත් නූලක් හෝ අංකයක් විග්රහ කරයි:
parseExpr = parseString <|> parseNumber
parseString = do
char '"'
x <- many (noneOf "\"")
char '"'
return (StringValue x)
parseNumber = do
num <- many1 digit
return (NumberValue (read num))
මෙහෙයුම් char
, digit
ආදිය ලස්සන සරල වේ. ඒවා ගැලපෙන්නේ හෝ නොගැලපේ. මැජික් යනු පාලක ප්රවාහය කළමනාකරණය කරන මොනාඩ් ය: තරඟයක් අසමත් වන තෙක් මෙහෙයුම් අනුක්රමිකව සිදු කරනු ලැබේ, එම අවස්ථාවේ දී මොනාඩ් නවතම දේ වෙත ආපසු යයි<|>
ඊළඟ විකල්පය උත්සාහ කරයි. නැවතත්, අමතර, ප්රයෝජනවත් අර්ථකථන කිහිපයක් සමඟ දම්වැල් දැමීමේ ක්රමයක්.
උදාහරණ 4: අසමමුහුර්ත වැඩසටහන්කරණය
ඉහත උදාහරණ Haskell දී ඇත, නමුත් පිටතට එය දුටුවේ එෆ් # ද monads සඳහා සහය දක්වයි. මෙම උදාහරණය ඩොන් සයිම් වෙතින් සොරකම් කර ඇත :
let AsyncHttp(url:string) =
async { let req = WebRequest.Create(url)
let! rsp = req.GetResponseAsync()
use stream = rsp.GetResponseStream()
use reader = new System.IO.StreamReader(stream)
return reader.ReadToEnd() }
මෙම ක්රමය වෙබ් පිටුවක් ලබා ගනී. පන්ච් රේඛාව යනු භාවිතා කිරීමයිGetResponseAsync
- එය ඇත්ත වශයෙන්ම වෙනම නූල් එකක ප්රතිචාරය එනතෙක් බලා සිටින අතර ප්රධාන නූල් ශ්රිතයෙන් නැවත පැමිණේ. ප්රතිචාරය ලැබුණු විට අවසාන පේළි තුන ක්රියාත්මක වන්නේ නූල් මත ය.
වෙනත් බොහෝ භාෂාවලින් ඔබට ප්රතිචාරය හසුරුවන රේඛා සඳහා වෙනම ශ්රිතයක් නිර්මාණය කිරීමට සිදුවේ. මෙම async
monad එහි ම මත වාරණ "භේදය" කිරීමට හැකි වන අතර, අවසාන භාගය ඝාතනය වීමයි. ( async {}
සින්ටැක්ස් මඟින් පෙන්නුම් කරන්නේ බ්ලොක් එකේ පාලන ප්රවාහය async
මොනාඩ් විසින් අර්ථ දක්වා ඇති බවයි .)
ඔවුන් වැඩ කරන ආකාරය
ඉතින් මොනාඩ් විසින් මේ සියලු විසිතුරු පාලන ප්රවාහ කටයුතු කරන්නේ කෙසේද? ඩූ-බ්ලොක් එකක ඇත්ත වශයෙන්ම සිදුවන්නේ (හෝ ගණනය කිරීමේ ප්රකාශනයක් ඒවා එෆ් # ලෙස හැඳින්වෙන පරිදි), සෑම මෙහෙයුමක්ම (මූලික වශයෙන් සෑම පේළියක්ම) වෙනම නිර්නාමික ශ්රිතයකින් ඔතා තිබීමයි. මෙම කාර්යයන් පසුව bind
ක්රියාකරු ( >>=
හැස්කෙල් හි අක්ෂර වින්යාසය ) භාවිතා කරයි. සිටbind
මෙහෙයුම මඟින් කාර්යයන් ඒකාබද්ධ වන , එය සුදුසු යැයි පෙනෙන පරිදි ඒවා ක්රියාත්මක කළ හැකිය: අනුක්රමිකව, කිහිප වතාවක්, ප්රතිලෝමව, සමහරක් ඉවතලන්න, සමහරක් එය දැනෙන විට වෙනම නූලක් මත ක්රියාත්මක කරන්න.
උදාහරණයක් ලෙස, මෙය උදාහරණ 2 සිට IO- කේතයේ පුළුල් කළ අනුවාදය වේ:
putStrLn "What is your name?"
>>= (\_ -> getLine)
>>= (\name -> putStrLn ("Welcome, " ++ name ++ "!"))
මෙය කැතයි, නමුත් ඇත්ත වශයෙන්ම සිදුවන්නේ කුමක්ද යන්න වඩාත් පැහැදිලිය. මෙම >>=
ක්රියාකරු මැජික් කොටස වන්නේ: එය නව වටිනාකමක් නිෂ්පාදනය කිරීමට, (වම් පැත්තේ) අගය ගනී උත්සවයකට (දකුණු පැත්තේ) සමග එය සම්බන්ධ කර ඇත. මෙම නව අගය ඊළඟ >>=
ක්රියාකරු විසින් ගෙන නැවත ශ්රිතයක් සමඟ ඒකාබද්ධ කර නව අගයක් නිපදවයි. >>=
කුඩා ඇගයුම්කරුවෙකු ලෙස දැකිය හැකිය.
>>=
විවිධ වර්ග සඳහා අධික ලෙස පටවා ඇති බව සලකන්න , එබැවින් සෑම මොනාඩ් එකකටම එය ක්රියාත්මක වේ >>=
. (දාමයේ ඇති සියලුම මෙහෙයුම් එකම මොනාඩ් වර්ගයට අයත් විය යුතුය, එසේ >>=
නොමැතිනම් ක්රියාකරු ක්රියා නොකරනු ඇත.)
සරළව ක්රියාත්මක කළ හැකි සරලම >>=
ක්රියාව වම්පස ඇති අගය ගෙන එය දකුණු පස ඇති ශ්රිතයට අදාළ කර ප්රති result ලය ලබා දෙයි, නමුත් පෙර කී පරිදි, මොනාඩ් ක්රියාත්මක කිරීමේදී අමතර යමක් සිදුවෙමින් පවතින විට සමස්ත රටාවම ප්රයෝජනවත් වන්නේ කුමක් ද? >>=
.
එක් මෙහෙයුමක සිට තවත් මෙහෙයුමකට අගයන් ලබා දෙන්නේ කෙසේද යන්න පිළිබඳ අමතර බුද්ධියක් ඇත, නමුත් මේ සඳහා හැස්කල් වර්ගයේ පද්ධතිය පිළිබඳ ගැඹුරු පැහැදිලි කිරීමක් අවශ්ය වේ.
සාරාංශ ගත
හස්කල් පදයට අනුව මොනාඩ් යනු පරාමිතිගත වර්ගයකි, එය මොනාඩ් වර්ගයේ පන්තියේ නිදසුනකි, එය >>=
තවත් ක්රියාකරුවන් කිහිප දෙනෙකු සමඟ අර්ථ දක්වයි . ගිහියන්ගේ වචන වලට අනුව, මොනාඩ් යනු >>=
මෙහෙයුම අර්ථ දක්වන වර්ගයකි .
තුල ම >>=
ක්රියාත්මක chaining හුදෙක් පා ගමනින් යාමට මාර්ගය, නමුත් "ගිලාබැසීම" වැහෙන වන කරන්න-අංකනය ඉදිරියේ සමග, monadic මෙහෙයුම්, ඉතා ලස්සන හා ප්රයෝජනවත් වියුක්තීකරණය බවට පත්වන භාෂාව ප්රයෝජනවත් බොහෝ ස්ථාන, සහ ප්රයෝජනවත් භාෂාවෙන් ඔබේම කුඩා භාෂා නිර්මාණය කිරීම සඳහා.
මොනාඩ්ස් අමාරු ඇයි?
බොහෝ හස්කල් ඉගෙන ගන්නන්ට, මොනාඩ්ස් යනු ගඩොල් බිත්තියක් මෙන් පහර දෙන බාධකයකි. මොනාඩ්ස් යනු සංකීර්ණ ඒවා නොවේ, නමුත් ක්රියාත්මක කිරීම පරාමිතිගත වර්ග, වර්ග පන්ති සහ වෙනත් බොහෝ දියුණු හැස්කල් අංග මත රඳා පවතී. ගැටළුව වන්නේ හස්කල් අයි / ඕ පදනම් වී ඇත්තේ මොනාඩ්ස් මත වන අතර නව භාෂාවක් ඉගෙන ගැනීමේදී ඔබ තේරුම් ගත යුතු පළමු දේවලින් එකක් වන්නේ අයි / ඕ ය - සියල්ලට පසු, කිසිවක් නිෂ්පාදනය නොකරන වැඩසටහන් නිර්මාණය කිරීම එතරම් විනෝදයක් නොවේ ප්රතිදානය. මෙම කුකුල් මස් හා බිත්තර ගැටලුවට මට ක්ෂණික විසඳුමක් නොමැත, භාෂාවේ වෙනත් කොටස් සමඟ ඔබට ප්රමාණවත් අත්දැකීම් ලැබෙන තුරු I / O “මැජික් මෙහි සිදු වේ” වැනි ප්රතිකාර කිරීම හැර. සමාවන්න.
මොනාඩ්ස් පිළිබඳ විශිෂ්ට බ්ලොග් අඩවිය: http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html
"මොනාඩ් යනු කුමක්ද" යන්න පැහැදිලි කිරීම "අංකයක් යනු කුමක්ද?" අපි නිතරම අංක භාවිතා කරමු. නමුත් ඔබට සංඛ්යා ගැන කිසිවක් නොදන්නා කෙනෙකු හමු වූ බව සිතන්න. කොහොමද සාජන් මහත්තයා ඔබ අංක දේ ඔබ පැහැදිලි කරන්නේ කෙසේද? එය ප්රයෝජනවත් විය හැක්කේ මන්දැයි ඔබ විස්තර කිරීමට පටන් ගන්නේ කෙසේද?
මොනාඩ් යනු කුමක්ද? කෙටි පිළිතුර: එය එකට දම්වැල් දැමීමේ මෙහෙයුම් ක්රමයකි.
සාරාංශයක් ලෙස, ඔබ ක්රියාත්මක කිරීමේ පියවර ලියන අතර ඒවා “බන්ධන ශ්රිතය” සමඟ සම්බන්ධ කරයි. (හස්කල් හි එය නම් කර ඇත >>=
.) ඔබට ඇමතුම් බන්ධන ක්රියාකරුට ලිවිය හැකිය, නැතහොත් ඔබට සින්ටැක්ස් සීනි භාවිතා කළ හැකි අතර එමඟින් සම්පාදකයා එම ක්රියාකාරී ඇමතුම් ඔබ වෙනුවෙන් ඇතුළත් කරයි. කෙසේ වෙතත්, එක් එක් පියවර මෙම බන්ධන ශ්රිතයට ඇමතුමක් මගින් වෙන් කරනු ලැබේ.
එබැවින් බන්ධන ශ්රිතය අර්ධ සළකුණක් වැනි ය; එය ක්රියාවලියක පියවර වෙන් කරයි. බන්ධන ශ්රිතයේ කාර්යය වන්නේ පෙර පියවරෙන් ප්රතිදානය ලබා ගැනීම සහ එය ඊළඟ පියවරට පෝෂණය කිරීමයි.
ඒක එතරම් අමාරු නැහැ, හරිද? නමුත් මොනාඩ් වර්ග එකකට වඩා තිබේ. මන්ද? කෙසේද?
හොඳයි, බඳින්න කාර්යය කළ හැකි එක් පියවරක් සිට ප්රතිඵලයක් ගන්න, සහ ඊළඟ පියවර එය පෝෂණය. නමුත් මොනාඩ් කරන්නේ “සියල්ලම” නම් ... එය ඇත්තෙන්ම එතරම් ප්රයෝජනවත් නොවේ. එය තේරුම් ගැනීම වැදගත්ය: සෑම ප්රයෝජනවත් මොනාඩ් එකක්ම මොනාඩ් වීමට අමතරව වෙනත් දෙයක් කරයි. සෑම ප්රයෝජනවත් මොනාඩ් එකකටම “විශේෂ බලයක්” ඇත, එය අද්විතීය කරයි.
( විශේෂ කිසිවක් නොකරන මොනාඩ් එකක් "අනන්යතා මොනාඩ්" ලෙස හැඳින්වේ. අනන්යතා ශ්රිතය මෙන් මෙය මුළුමනින්ම අර්ථ විරහිත දෙයක් සේ පෙනේ, නමුත් එසේ නොවන බව පෙනේ ... නමුත් එය තවත් කතාවකි ™.)
මූලික වශයෙන්, එක් එක් මොනාඩ් සතුව බන්ධන ශ්රිතය ක්රියාත්මක කිරීම ඇත. තවද ඔබට බන්ධන ශ්රිතයක් ලිවිය හැකිය, එය ක්රියාත්මක කිරීමේ පියවර අතර කේන්දර කාරණා කරයි. උදාහරණයක් වශයෙන්:
සෑම පියවරක්ම සාර්ථක / අසාර්ථක දර්ශකයක් ලබා දෙන්නේ නම්, ඔබට ඊළඟ පියවර ක්රියාත්මක කළ හැක්කේ පෙර පියවර සාර්ථක වුවහොත් පමණි. මේ ආකාරයට, අසාර්ථක පියවරක් ඔබ වෙතින් කිසිදු කොන්දේසි සහිත පරීක්ෂණයකින් තොරව සම්පූර්ණ අනුක්රමය “ස්වයංක්රීයව” නවතා දමයි. ( අසමත් මොනාඩ් .)
මෙම අදහස දීර් ing කරමින් ඔබට "ව්යතිරේක" ක්රියාත්මක කළ හැකිය. ( දෝෂ මොනාඩ් හෝ ව්යතිරේක මොනාඩ් .) එය භාෂා අංගයක් නොව ඔබම නිර්වචනය කර ඇති නිසා, ඒවා ක්රියාත්මක වන ආකාරය ඔබට අර්ථ දැක්විය හැකිය. (උදා: සමහර විට ඔබට පළමු ව්යතිරේක දෙක නොසලකා හැර තුන්වන ව්යතිරේකය විසි කළ විට පමණක් ගබ්සා කිරීමට අවශ්ය වනු ඇත .)
ඔබට සෑම පියවරක්ම බහුවිධ ප්රති results ල ලබා දිය හැකි අතර, ඒවා මත බන්ධන ශ්රිත ලූපයක් තබාගෙන, එක් එක් පියවර ඔබ වෙනුවෙන් ඊළඟ පියවරට පෝෂණය කරයි. මේ ආකාරයෙන්, බහුවිධ ප්රති .ල සමඟ කටයුතු කිරීමේදී ඔබට සෑම තැනකම ලූප ලිවීම අවශ්ය නොවේ. බන්ධන ශ්රිතය “ස්වයංක්රීයව” ඔබ වෙනුවෙන් ඒ සියල්ල කරයි. ( ලැයිස්තුව මොනාඩ් .)
"ප්රති result ලයක්" එක් පියවරක සිට තවත් පියවරක් පසු කිරීම මෙන්ම, ඔබට බන්ධන ශ්රිතය මඟින් අමතර දත්ත පසුකර යා හැකිය . මෙම දත්ත දැන් ඔබේ ප්රභව කේතයේ නොපෙන්වයි, නමුත් සෑම කාර්යයක් සඳහාම එය අතින් යැවීමකින් තොරව ඔබට ඕනෑම තැනක සිට ප්රවේශ විය හැකිය. (පා er කයා මොනාඩ් .)
"අතිරේක දත්ත" ප්රතිස්ථාපනය කිරීම සඳහා ඔබට එය සෑදිය හැකිය. සැබවින්ම විනාශකාරී යාවත්කාලීනයන් නොකර විනාශකාරී යාවත්කාලීන කිරීම් අනුකරණය කිරීමට මෙය ඔබට ඉඩ දෙයි . ( රාජ්ය මොනාඩ් සහ එහි ous ාති සහෝදරයා වන ලේඛකයා මොනාඩ් .)
ඔබ විනාශකාරී යාවත්කාලීනයන් පමණක් අනුකරණය කරන නිසා, ඔබට සැබෑ විනාශකාරී යාවත්කාලීනයන් සමඟ කළ නොහැකි දේවල් සුළු වශයෙන් කළ හැකිය . උදාහරණයක් ලෙස, ඔබට අවසන් යාවත්කාලීන කිරීම අහෝසි කළ හැකිය , නැතහොත් පැරණි අනුවාදයකට ආපසු යා හැකිය .
ඔබ ගණනය කිරීම් කළ හැකි, monad කළ හැකි නැගී සිටියේය ඔබ ඔබේ වැඩ ගැන මදක් නැවතී හැකි නිසා, අභ්යන්තර රාජ්ය දත්ත සමඟ ගිහින් ටින්කර්, පසුව එය නැවත ආරම්භ.
ඔබට "අඛණ්ඩව" මොනාඩ් ලෙස ක්රියාත්මක කළ හැකිය. මෙය මිනිසුන්ගේ මනස බිඳ දැමීමට ඔබට ඉඩ සලසයි !
මේ සියල්ල සහ තවත් බොහෝ දේ මොනාඩ්ස් සමඟ කළ හැකිය. ඇත්ත වශයෙන්ම, මොනාඩ්ස් නොමැතිව මේ සියල්ලම පරිපූර්ණ ලෙස කළ හැකිය . මොනාඩ්ස් භාවිතා කිරීම ඉතා පහසු ය .
ඇත්ත වශයෙන්ම, මොනාඩ්ස් පිළිබඳ පොදු අවබෝධයට පටහැනිව, ඔවුන්ට රාජ්ය සමග කිසිදු සම්බන්ධයක් නැත. මොනාඩ්ස් යනු හුදෙක් දේවල් ඔතා තැබීමේ ක්රමයක් වන අතර, ඔතා ඇති දෑ ලිහා නොගෙන මෙහෙයුම් කිරීමට ක්රමවේදයන් සපයයි.
උදාහරණයක් ලෙස, ඔබට තවත් එකක් එතීමට වර්ගයක් නිර්මාණය කළ හැකිය, හස්කල් හි:
data Wrapped a = Wrap a
අපි අර්ථ දක්වන දේවල් එතීමට
return :: a -> Wrapped a
return x = Wrap x
නොකැඩීමකින් තොරව මෙහෙයුම් සිදු කිරීම සඳහා, ඔබට ශ්රිතයක් ඇති බව පවසන්න f :: a -> b
, එවිට ඔතා ඇති අගයන් මත ක්රියා කිරීම සඳහා එම ශ්රිතය ඔසවා තැබීමට ඔබට මෙය කළ හැකිය :
fmap :: (a -> b) -> (Wrapped a -> Wrapped b)
fmap f (Wrap x) = Wrap (f x)
තේරුම් ගත යුතු සියල්ල එයයි. කෙසේ වෙතත්, මෙම එසවීම සිදු කිරීම සඳහා වඩාත් පොදු කාර්යයක් ඇති බව පෙනේ , එනම් bind
:
bind :: (a -> Wrapped b) -> (Wrapped a -> Wrapped b)
bind f (Wrap x) = f x
bind
ඊට වඩා ටිකක් වැඩියෙන් කළ හැකි fmap
නමුත් අනෙක් අතට නොවේ. ඇත්තටම, fmap
අනුව පමණක් අර්ථ දැක්විය හැකිය bind
සහ return
. ඉතින්, මොනාඩ් එකක් නිර්වචනය කිරීමේදී .. ඔබ එහි වර්ගය ලබා දෙයි (මෙන්න එය විය Wrapped a
) ඉන්පසු එහි return
සහ bind
මෙහෙයුම් ක්රියාත්මක වන ආකාරය පවසන්න .
සිසිල් දෙය නම්, මෙය එබඳු පොදු රටාවක් බවට පත්වන අතර එය සෑම තැනකම මතු වන අතර, තත්වය පිරිසිදු ආකාරයකින් සංවර්ධනය කිරීම ඒවායින් එකක් පමණි.
ක්රියාකාරී පරායත්තතා හඳුන්වාදීම සඳහා මොනාඩ්ස් භාවිතා කළ හැකි ආකාරය පිළිබඳ හොඳ ලිපියක් සඳහා සහ එමඟින් ඇගයුම් අනුපිළිවෙල පාලනය කිරීම, එය හස්කල්ගේ අයිඕ මොනාඩ් හි භාවිතා වන ආකාරයටම, අයිඕ ඉන්සයිඩ් බලන්න .
මොනාඩ්ස් තේරුම් ගැනීම සඳහා, ඒ ගැන ඕනෑවට වඩා කරදර නොවන්න. ඔබට සිත්ගන්නා දේ ඔවුන් ගැන කියවන්න, ඔබට එකවරම තේරෙන්නේ නැත්නම් කරදර නොවන්න. එවිට හස්කල් වැනි භාෂාවකින් කිමිදීම යනු යා යුතු මාර්ගයයි. මොනාඩ්ස් යනු ප්රායෝගිකව ඔබේ මොළයට උපක්රම අවබෝධ කර ගත හැකි එක් දෙයකි, දිනක් ඔබ හදිසියේම තේරුම් ගත්තා ඔබ ඒවා තේරුම් ගත් බව.
නමුත්, ඔබට මොනාඩ්ස් නිර්මාණය කළ හැකිය!
sigfpe පවසයි:
නමුත් මේ සියල්ලම මොනාඩ්ස් හඳුන්වා දෙන්නේ පැහැදිලි කිරීමක් අවශ්ය වන අද්භූත දෙයක් ලෙස ය. නමුත් මට තර්ක කිරීමට අවශ්ය වන්නේ ඔවුන් කිසිසේත්ම ව්යාකූල නොවන බවයි. ඇත්ත වශයෙන්ම, ක්රියාකාරී ක්රමලේඛනයේ විවිධ ගැටලුවලට ඔබ මුහුණ දෙනු ඇත, නිසැකවම, ඇතැම් විසඳුම් වෙත ඔබව යොමු කරනු ඇත, ඒ සියල්ල මොනාඩ් සඳහා උදාහරණ වේ. ඇත්ත වශයෙන්ම, ඔබ දැනටමත් නොමැති නම් ඒවා දැන් නිර්මාණය කිරීමට මම බලාපොරොත්තු වෙමි. මෙම විසඳුම් සියල්ලම වෙස්වළා ගැනීමේදී එකම විසඳුම බව සැලකිල්ලට ගැනීම කුඩා පියවරකි. මෙය කියවීමෙන් පසු, මොනාඩ් වල ඇති වෙනත් ලියකියවිලි තේරුම් ගැනීමට ඔබට වඩා හොඳ තත්වයක සිටිය හැකි බැවින් ඔබ දකින සියල්ල ඔබ දැනටමත් නිර්මාණය කර ඇති දෙයක් ලෙස හඳුනා ගනු ඇත.
මොනාඩ්ස් විසින් විසඳීමට උත්සාහ කරන බොහෝ ගැටලු අතුරු ආබාධ පිළිබඳ ගැටළුව හා සම්බන්ධ වේ. එබැවින් අපි ඔවුන් සමඟ ආරම්භ කරමු. (අතුරු ආබාධ හැසිරවීමට වඩා වැඩි යමක් කිරීමට මොනාඩ්ස් ඔබට ඉඩ දෙන බව සලකන්න, විශේෂයෙන් බොහෝ වර්ගවල බහාලුම් වස්තු මොනාඩ් ලෙස දැකිය හැකිය. අනෙක්.)
C ++ වැනි අත්යවශ්ය ක්රමලේඛන භාෂාවක, ශ්රිත ගණිතයේ කාර්යයන් මෙන් ක්රියා නොකරයි. උදාහරණයක් ලෙස, අපට C ++ ශ්රිතයක් ඇති අතර එය තනි පාවෙන ලක්ෂ්ය තර්කයක් ගෙන පාවෙන ලක්ෂ්ය ප්රති .ලයක් ලබා දෙයි. මතුපිටින් බැලූ විට එය ගණිතමය අනුරූප සිතියම් යථාර්ථයක් ලෙස පෙනේ, නමුත් C ++ ශ්රිතයකට එහි තර්ක මත රඳා පවතින සංඛ්යාවක් ආපසු ලබා දීමට වඩා වැඩි යමක් කළ හැකිය. ගෝලීය විචල්යයන්ගේ අගයන් කියවීමට හා ලිවීමට මෙන්ම තිරයට ප්රතිදානය ලිවීමට සහ පරිශීලකයාගෙන් ආදානය ලබා ගැනීමට එයට හැකිය. කෙසේ වෙතත්, පිරිසිදු ක්රියාකාරී භාෂාවක, ශ්රිතයකට කියවිය හැක්කේ එහි තර්ක වලින් එය සපයන දේ පමණක් වන අතර එය ලෝකයට බලපෑමක් ඇති කළ හැකි එකම ක්රමය එය ලබා දෙන අගයන් හරහා ය.
මොනාඩ් යනු මෙහෙයුම් දෙකක් ඇති දත්ත සමුදායකි: >>=
(අකා bind
) සහ return
(අකා unit
). return
අත්තනෝමතික අගයක් ගෙන එය සමඟ මොනාඩ් පිළිබඳ උදාහරණයක් නිර්මාණය කරයි. >>=
මොනාඩ්හි උදාහරණයක් ගෙන එය මත ශ්රිතයක් සිතියම් ගත කරයි. (ඔබ වඩාත් ක්රමලේඛන භාෂා ඔබ හිතුවක්කාරී අගය ගනී සහ ඒ වර්ගයක් නිර්මාණය කරන බවට උත්සවයකට ලියන්න නොහැකි සිට monad, datatype අමුතු ආකාරයේ බව දැනටමත් බලන්න පුළුවන්. Monads කාරුණික භාවිතා පරාමිතික බහුරූපතාව .)
හැස්කල් අංකනයෙහි, මොනාඩ් අතුරුමුහුණත ලියා ඇත
class Monad m where
return :: a -> m a
(>>=) :: forall a b . m a -> (a -> m b) -> m b
මෙම මෙහෙයුම් කීකරු ඇතැම් "නීති" කියනු ලැබේ, නමුත් එම terrifically වැදගත් නොවේ: මේ "නීති" පමණක් මෙහෙයුම් සංවේදී නිර්මාණයන් (එනම්, මූලික වශයෙන් හැසිරෙන යුතු ආකාරය සම්පාදනය කිරීමට >>=
සහ return
සාරධර්ම monad අවස්ථා බවට පරිවර්තනය කර ගැනීමට කරන ආකාරය පිළිබඳ එකඟ යුතු හා බව >>=
associative) වේ.
මොනාඩ්ස් යනු රාජ්යය සහ අයි / ඕ ගැන පමණක් නොවේ: ඒවා රාජ්ය, අයි / ඕ, ව්යතිරේක සහ නිර්ණය නොවන දේ සමඟ වැඩ කිරීම ඇතුළත් පොදු ගණනය කිරීමේ රටාවක් වියුක්ත කරයි. තේරුම් ගැනීමට ඇති සරලම මොනාඩ් ලැයිස්තු සහ විකල්ප වර්ග වේ:
instance Monad [ ] where
[] >>= k = []
(x:xs) >>= k = k x ++ (xs >>= k)
return x = [x]
instance Monad Maybe where
Just x >>= k = k x
Nothing >>= k = Nothing
return x = Just x
එහිදී []
සහ :
ලැයිස්තුව ඉදිකරන්නන් වන අතර, ++
එම අකාර වන අතර, Just
සහ Nothing
සිටින්නේ Maybe
ඉදිකරන්නන්. මෙම මොනාඩ් දෙකම ඔවුන්ගේ දත්ත වර්ග මත පොදු හා ප්රයෝජනවත් ගණනය කිරීමේ රටාවන් සංයුක්ත කරයි (අතුරු ආබාධ හෝ I / O සමඟ කිසිම සම්බන්ධයක් නැති බව සලකන්න).
මොනාඩ්ස් යනු කුමක්ද සහ ඒවා ප්රයෝජනවත් වන්නේ ඇයිද යන්න අගය කිරීම සඳහා සුළු නොවන හැස්කල් කේතයක් ලිවීමට ඔබ සැබවින්ම සෙල්ලම් කළ යුතුය.
Functor යනු කුමක්දැයි ඔබ මුලින්ම තේරුම් ගත යුතුය. ඊට පෙර, ඉහළ පෙළේ කාර්යයන් තේරුම් ගන්න.
ඒ උසස් පෙළ කාර්යය හුදෙක් තර්කය ලෙස උත්සවයකට ගත වන බව ශ්රිතයක් වේ.
ඒ functor ඕනෑම ආකාරයේ ඉදිකිරීම් T
සඳහා වැඩි ඇණවුම් කාර්යය එහි පවතී, එය අමතන්න map
, වර්ගය ශ්රිතයක් පරිවර්තනය වීම් බව a -> b
(ඕනෑම වර්ග දෙකක් ලබා දී a
සහ b
උත්සවයකට බවට) T a -> T b
. මෙම map
ශ්රිතය අනන්යතාවයේ සහ සංයුතියේ නීතිවලට අවනත විය යුතුය. පහත දැක්වෙන ප්රකාශ සියල්ලන්ටම සත්ය වන p
අතර q
(හස්කල් අංකනය):
map id = id
map (p . q) = map p . map q
නිදසුනක් ලෙස, ඉහත සඳහන් නීතිවලට අවනත List
වන ආකාරයේ ශ්රිතයක් සහිත නම් එය ඉදිකිරීම්කරුවෙකු ලෙස හැඳින්වේ (a -> b) -> List a -> List b
. එකම ප්රායෝගික ක්රියාත්මක කිරීම පැහැදිලිය. එහි List a -> List b
ප්රති function ලයක් ලෙස ලබා දී ඇති ලැයිස්තුවට වඩා (a -> b)
එක් එක් මූලද්රව්යය සඳහා ශ්රිතය කැඳවා ප්රති .ල ලැයිස්තුව නැවත ලබා දේ.
ඒ monad අවශ්යයෙන්ම පමණක් functor වේ T
, අමතර ක්රම දෙකක් සමග join
වර්ගයේ, T (T a) -> T a
සහ unit
(සමහර විට කැඳවා return
, fork
හෝ pure
) වර්ගයේ a -> T a
. හැස්කෙල් හි ලැයිස්තු සඳහා:
join :: [[a]] -> [a]
pure :: a -> [a]
එය ප්රයෝජනවත් වන්නේ ඇයි? ඔබට නිදසුනක් ලෙස, map
ලැයිස්තුවක් ලබා දෙන ශ්රිතයක් සහිත ලැයිස්තුවක් හරහා කළ හැකි බැවිනි. Join
එහි ප්රති ing ලයක් ලෙස ලැයිස්තු ලැයිස්තුව ගෙන ඒවා සංයුක්ත කරයි. List
මෙය කළ හැකි නිසා මොනාඩ් වේ.
ඔබට එය බව උත්සවයකට ලියන්න පුළුවන් map
නම්, join
. මෙම ශ්රිතය හැඳින්වෙන්නේ bind
, හෝ flatMap
, හෝ (>>=)
, හෝ (=<<)
. මෙය සාමාන්යයෙන් හැස්කෙල්හි මොනාඩ් නිදසුනක් ලබා දෙන ආකාරයයි.
මොනාඩ් විසින් ඇතැම් නීති සපුරාලිය join
යුතුය , එනම් එය අනුබද්ධ විය යුතුය. මෙහි අරුත වන්නේ, ඔබ විසින් අගය තිබේ නම් එහි අර්ථය වන්නේ x
වර්ගයේ [[[a]]]
පසුව join (join x)
තිබිය යුතුය join (map join x)
. හා pure
සඳහා අනන්යතාවය විය යුතුය join
, එවන් join (pure x) == x
.
[වියාචනය: මම තවමත් උත්සාහ කරන්නේ මොනාඩ්ස් සම්පූර්ණයෙන් පැහැර ගැනීමටයි. පහත දැක්වෙන්නේ මා මෙතෙක් තේරුම් ගෙන ඇති දෙයයි. එය වැරදියි නම්, දැනුමක් ඇති අයෙකු මට කාපට් අතුරා කතා කරනු ඇත.]
ආර්නර් මෙසේ ලිවීය.
මොනාඩ්ස් යනු හුදෙක් දේවල් ඔතා තැබීමේ ක්රමයක් වන අතර, ඔතා ඇති දෑ ලිහා නොගෙන මෙහෙයුම් කිරීමට ක්රමවේදයන් සපයයි.
එය හරියටම එයයි. අදහස මෙසේ ය:
ඔබ යම් ආකාරයක වටිනාකමක් ගෙන අතිරේක තොරතුරු සමඟ එය ඔතා. අගය එක්තරා ආකාරයක (උදා: පූර්ණ සංඛ්යාවක් හෝ නූලක්) මෙන්ම අතිරේක තොරතුරු එක්තරා ආකාරයක ය.
උදා, එම අමතර තොරතුරු a Maybe
හෝ a විය හැකිය IO
.
එවිට ඔබට සමහර අමතර ක්රියාකරුවන් සිටින අතර එම අමතර තොරතුරු රැගෙන යන අතරතුර ඔතා ඇති දත්ත ක්රියාත්මක කිරීමට ඔබට ඉඩ සලසයි. ඔතා ඇති අගය මත මෙහෙයුමේ හැසිරීම වෙනස් කරන්නේ කෙසේද යන්න තීරණය කිරීමට මෙම ක්රියාකරුවන් අතිරේක තොරතුරු භාවිතා කරයි.
උදා, a හෝ Maybe Int
විය හැකිය . දැන්, ඔබට කරන්න නම් කිරීමට , ක්රියාකරු ඔවුන් දෙදෙනාම නම් දකින්න පරීක්ෂා කරනු ඇත ඇතුලත ද, එසේ නම්, ඒ සඳහා unwrap ඇත s, ඔවුන් එකතු ක්රියාකරු සමත්, ඵලිත නැවත ආවරණය කරනවා නව සොයා (අ වලංගු වන ), ඒ අනුව ආපසු a . නමුත් ඔවුන්ගෙන් එක් අයෙකු ඇතුළත සිටියා නම්, මෙම ක්රියාකරු වහාම ආපසු එනු ඇත , එය නැවතත් වලංගු වේ . එමගින්, ඔබේ සාමාන්ය සංඛ්යා පමණක් යැයි මවා පාමින් ඒවා මත ගණිතය සිදු කළ හැකිය. ඔබ ලබා ගැනීමට නම් , ඔබේ සමීකරණ තවමත් නිවැරදි ප්රති result ල ලබා දෙනු ඇත - ඔබ සෑම තැනකම පැටව් ගසන්නේ නැතිව .Just Int
Nothing
Maybe Int
Maybe Int
Just Int
Int
Int
Just Int
Maybe Int
Maybe Int
Nothing
Nothing
Maybe Int
Maybe Int
Nothing
Nothing
නමුත් උදාහරණය වන්නේ කුමක් සඳහාද Maybe
යන්නයි. අමතර තොරතුරු යනු නම් IO
, ඒ සඳහා අර්ථ දක්වා ඇති විශේෂ ක්රියාකරු IO
ඒ වෙනුවට කැඳවනු ලබන අතර, එකතු කිරීම සිදු කිරීමට පෙර එයට සම්පූර්ණයෙන්ම වෙනස් දෙයක් කළ හැකිය. (හරි, දෙකක් IO Int
එකතු කිරීම විකාර සහගතයි - මට තවම විශ්වාස නැත.) (එසේම, ඔබ Maybe
උදාහරණයට අවධානය යොමු කළේ නම් , “අමතර දේවල් සමඟ වටිනාකමක් ඔතා ගැනීම” සැමවිටම නිවැරදි නොවන බව ඔබ දැක ඇත. නමුත් එය දුෂ්කර ය නිරවුල් නොවී නිරවද්ය, නිවැරදි හා නිරවද්ය වීමට.)
මූලික වශයෙන්, “මොනාඩ්” යන්නෙහි දළ වශයෙන් “රටාව” යන්නයි . නමුත් අවිධිමත් ලෙස පැහැදිලි කරන ලද සහ විශේෂයෙන් නම් කරන ලද රටා වලින් පිරුණු පොතක් වෙනුවට, ඔබට දැන් භාෂා සැකැස්මක් ඇත - වාක්ය ඛණ්ඩය සහ සියල්ල - ඔබේ වැඩසටහනේ දේවල් ලෙස නව රටා ප්රකාශ කිරීමට ඔබට ඉඩ සලසයි . (මෙහි නිරවද්යතාවය නම් සියලු රටාවන් විශේෂිත ආකෘතියක් අනුගමනය කළ යුතු ය, එබැවින් මොනාඩ් රටාවක් තරම් සාමාන්ය නොවේ. නමුත් මම සිතන්නේ එය බොහෝ දෙනා දන්නා සහ තේරුම් ගන්නා ආසන්නතම යෙදුමයි.)
මිනිසුන් මොනාඩ්ස් එතරම් අවුල් සහගත වන්නේ එබැවිනි: මන්ද ඔවුන් එවැනි සාමාන්ය සංකල්පයක් වන බැවිනි. මොනාඩ් එකක් සෑදෙන්නේ කුමක් දැයි විමසීමට සමාන දෙයක් අපැහැදිලි වන්නේ යමක් රටාවක් කරන්නේ කුමක් දැයි විමසීමට ය.
රටාවක් පිළිබඳ අදහස සඳහා භාෂාවෙන් සින්ටැක්ටික් ආධාරක තිබීමේ ඇඟවුම් ගැන සිතා බලන්න: හතර කල්ලිය කියවීම වෙනුවට පොත විශේෂිත රටාවක් තැනීම කටපාඩම් කිරීම වෙනුවට, ඔබ මෙම රටාව අ nost ෙයවාදියෙකු තුළ ක්රියාත්මක කරන කේතයක් ලියයි. සාමාන්ය ක්රමය එක් වරක් ඔබ අවසන් කර ඇත! අමුත්තෙකු හෝ උපාය මාර්ගයක් හෝ ෆැසෙඩ් වැනි ඕනෑම දෙයක් ඔබට නැවත භාවිතා කළ හැකිය, ඔබේ කේතයේ ඇති ක්රියාකාරකම් නැවත නැවත ක්රියාත්මක නොකර එය සමඟ එය අලංකාර කිරීමෙන්.
මොනාඩ්ස් තේරුම් ගන්නා පුද්ගලයින් ඒවා එතරම් ප්රයෝජනවත් වන්නේ එබැවිනි : බුද්ධිමය ස්නොබ්වරු අවබෝධය ගැන ආඩම්බර වන ඇත් දත් කුළුණු සංකල්පයක් නොවේ (හරි, ඇත්තෙන්ම එය තේහී), නමුත් ඇත්ත වශයෙන්ම කේතය සරල කරයි.
M (M a) -> M a
. ඔබට එය එක් වර්ගයක් බවට පත් කළ හැකි වීම M a -> (a -> M b) -> M b
ඒවා ප්රයෝජනවත් වේ.
බොහෝ වෙහෙස මහන්සි වී වැඩ කිරීමෙන් පසු, මම අවසානයේ මොනාඩ් තේරුම් ගත්තා. ඉහළින්ම ඡන්දය දුන් පිළිතුර පිළිබඳ මගේම දිගු විවේචනයක් නැවත කියවීමෙන් පසුව, මම මෙම පැහැදිලි කිරීම ඉදිරිපත් කරමි.
මොනාඩ්ස් තේරුම් ගැනීම සඳහා පිළිතුරු සැපයිය යුතු ප්රශ්න තුනක් තිබේ:
මගේ මුල් අදහස් දැක්වීමේදී මා සඳහන් කළ පරිදි, බොහෝ මොනාඩ් පැහැදිලි කිරීම් 3 වන ප්රශ්නයට, රහිතව, සහ ප්රමාණවත් ලෙස 2 වන ප්රශ්නය හෝ 1 වන ප්රශ්නය ආවරණය කිරීමට පෙර හසු වේ.
ඔබට මොනාඩ් අවශ්ය වන්නේ ඇයි?
හස්කල් වැනි පිරිසිදු ක්රියාකාරී භාෂාවන් සී හෝ ජාවා වැනි අත්යවශ්ය භාෂාවන්ට වඩා වෙනස් ය, පිරිසිදු ක්රියාකාරී වැඩසටහනක් නිශ්චිත අනුපිළිවෙලකට ක්රියාත්මක නොකෙරේ, වරකට එක් පියවරක්. හැස්කල් වැඩසටහනක් ගණිතමය ශ්රිතයකට වඩා සමාන වන අතර, එමඟින් ඔබට ඕනෑම විභව අනුපිළිවෙලකින් “සමීකරණය” විසඳිය හැකිය. මෙය ප්රතිලාභ ගණනාවක් ලබා දෙන අතර, ඒ අතර එය ඇතැම් ආකාරයේ දෝෂ ඇතිවීමේ හැකියාව ඉවත් කරයි, විශේෂයෙන් "රාජ්යය" වැනි දේවලට අදාළ ඒවා.
කෙසේ වෙතත්, මෙම ක්රමලේඛන විලාසය සමඟ විසඳීමට එතරම් සරල නොවන ඇතැම් ගැටලු තිබේ. කොන්සෝල ක්රමලේඛනය සහ අයි / ඕ ගොනුව වැනි සමහර දේට නිශ්චිත අනුපිළිවෙලකට සිදුවිය යුතු දේ හෝ තත්වය පවත්වා ගැනීමට අවශ්ය වේ. මෙම ගැටළුව සමඟ කටයුතු කළ හැකි එක් ක්රමයක් නම් ගණනය කිරීමේ තත්වය නිරූපණය කරන ආකාරයේ වස්තුවක් නිර්මාණය කිරීම සහ රාජ්ය වස්තුවක් ආදානය ලෙස ගන්නා ශ්රිත මාලාවක් නිර්මාණය කිරීම සහ නව වෙනස් කරන ලද රාජ්ය වස්තුවක් ආපසු ලබා දීම ය.
එබැවින් අපි කොන්සෝල තිරයක තත්වය නිරූපණය කරන උපකල්පිත "රාජ්ය" අගයක් නිර්මාණය කරමු. හරියටම මෙම අගය ගොඩනඟා ඇති ආකාරය වැදගත් නොවේ, නමුත් එය තිරයේ දැනට පෙනෙන දේ නිරූපණය කරන බයිට් දිග ඇස්කි අක්ෂර මාලාවක් සහ ව්යාජ කේතයෙන් පරිශීලකයා විසින් ඇතුළත් කළ අවසන් ආදාන රේඛාව නිරූපණය කරන අරාවකි. කොන්සෝලයේ තත්වය, වෙනස් කිරීම සහ නව කොන්සෝල තත්වයක් ලබා දෙන සමහර කාර්යයන් අපි අර්ථ දක්වා ඇත්තෙමු.
consolestate MyConsole = new consolestate;
එබැවින් කොන්සෝල ක්රමලේඛනය කිරීම සඳහා, නමුත් පිරිසිදු ක්රියාකාරී ආකාරයකින්, ඔබ එකිනෙකා තුළ ක්රියාකාරී ඇමතුම් රාශියක් කැදැල්ලට ගත යුතුය.
consolestate FinalConsole = print(input(print(myconsole, "Hello, what's your name?")),"hello, %inputbuffer%!");
මේ ආකාරයට ක්රමලේඛනය කිරීම “පිරිසිදු” ක්රියාකාරී ශෛලිය පවත්වා ගෙන යන අතරම කොන්සෝලයෙහි වෙනස්කම් නිශ්චිත අනුපිළිවෙලකට සිදු කිරීමට බල කරයි. නමුත්, ඉහත උදාහරණයේ දී මෙන් වරකට මෙහෙයුම් කිහිපයකට වඩා වැඩි යමක් කිරීමට අපට අවශ්ය වනු ඇත. ඒ ආකාරයෙන් කූඩු දැමීමේ කාර්යයන් අශෝභන වීමට පටන් ගනී. අපට අවශ්ය වන්නේ, ඉහත සඳහන් ආකාරයටම එකම දේ කරන කේතය, නමුත් මේ ආකාරයට තව ටිකක් ලියා ඇත:
consolestate FinalConsole = myconsole:
print("Hello, what's your name?"):
input():
print("hello, %inputbuffer%!");
මෙය සැබවින්ම එය ලිවීමට වඩාත් පහසු ක්රමයක් වනු ඇත. නමුත් අපි එය කරන්නේ කෙසේද?
මොනාඩ් යනු කුමක්ද?
ඔබ වර්ගයක් (වැනි consolestate
) ඇති විට, එම වර්ගයේ ක්රියාකාරීත්වය සඳහා විශේෂයෙන් නිර්මාණය කර ඇති කාර්යයන් සමූහයක් සමඟ, ඔබට :
ස්වයංක්රීයව (බන්ධනය) වැනි ක්රියාකරුවෙකු නිර්වචනය කිරීමෙන් ඔබට මේ සියල්ලේ සම්පූර්ණ පැකේජය “මොනාඩ්” බවට පත් කළ හැකිය. එහි වම්පස ප්රතිලාභ අගයන්, දකුණු පස ඇති ක්රියාකාරී පරාමිතීන් සහ lift
සාමාන්ය කාර්යයන් හරවන ක්රියාකරුවෙකු එම විශේෂිත බන්ධන ක්රියාකරු සමඟ ක්රියා කරන කාර්යයන් බවට පෝෂණය කරයි .
මොනාඩ් ක්රියාත්මක කරන්නේ කෙසේද?
වෙනත් පිළිතුරු බලන්න, ඒ පිළිබඳ විස්තර වෙත පනින්නට නිදහස් බව පෙනේ.
මීට වසර කිහිපයකට පෙර මෙම ප්රශ්නයට පිළිතුරක් ලබා දීමෙන් පසුව, එම ප්රතිචාරය වැඩි දියුණු කර සරල කළ හැකි යැයි මම විශ්වාස කරමි ...
මොනාඩ් යනු ක්රියාකාරී සංයුතියකි, එය සංයුතියේ ශ්රිතයක් භාවිතා කරමින් සමහර ආදාන අවස්ථා සඳහා ප්රතිකාරය බාහිරකරණය කරයි bind
.
සාමාන්ය සංයුතියේ දී, ශ්රිතය, compose (>>)
රචනා කරන ලද ශ්රිතය එහි පූර්වගාමියාගේ අනුපිළිවෙලට යෙදීම සඳහා යොදා ගනී. වැදගත් වන්නේ, රචනා කරන ලද ශ්රිතය එහි ආදානයේ සියලු අවස්ථා හැසිරවීමට අවශ්ය වේ.
(x -> y) >> (y -> z)
ආදාන ප්රතිව්යුහගත කිරීමෙන් මෙම සැලසුම වැඩිදියුණු කළ හැකි අතර එමඟින් අදාළ රාජ්යයන් වඩාත් පහසුවෙන් ප්රශ්න කරනු ලැබේ. එබැවින්, y
අගය වෙනුවට වලංගුභාවය පිළිබඳ සංකල්පයක් ඇතුළත් කළ හොත් Mb
, අගය වැනි විය හැකිය .(is_OK, b)
y
නිදසුනක් ලෙස, ආදානය විය හැක්කේ සංඛ්යාවක් පමණක් වන විට, නිසි ලෙස සංඛ්යාවක් අඩංගු විය හැකි හෝ නැති විය හැකි නූලක් ආපසු ලබා දෙනවා වෙනුවට, ඔබට bool
වලංගු අංකයක් සහ අංකයක් වැනි අංකයක් ඇති බව දක්වමින් වර්ගය ප්රතිව්යුහගත කළ හැකිය bool * float
. රචනා කරන ලද ශ්රිතයන්ට දැන් අංකයක් තිබේද යන්න තීරණය කිරීම සඳහා ආදාන නූලක් විග්රහ කිරීමට අවශ්ය නොවන නමුත් හුදෙක් bool
ටුපල් එකක කොටස පරීක්ෂා කළ හැකිය .
(Ma -> Mb) >> (Mb -> Mc)
මෙන්න, නැවතත්, සංයුතිය ස්වභාවිකව සිදු වන compose
අතර ඒ නිසා සෑම ශ්රිතයක්ම එහි ආදානයේ සියලු අවස්ථා තනි තනිව හැසිරවිය යුතුය, නමුත් එසේ කිරීම දැන් වඩා පහසුය.
කෙසේ වෙතත්, සිද්ධියක් හසුරුවා ගැනීම සාමාන්ය දෙයක් වන එම කාලය තුළ ප්රශ්න කිරීමේ උත්සාහය බාහිරකරණය කිරීමට අපට හැකි නම් කුමක් කළ යුතුද? උදාහරණයකට, අපගේ ක්රියාමාර්ගය ඒකන් මෙන් හරි නොමැති වූ විට කිසිවක් කර නැත නම් is_OK
වේ false
. එය සිදු කළේ නම්, රචනා කරන ලද කාර්යයන් සඳහා එම අවස්ථාවම හසුරුවා ගැනීමට අවශ්ය නොවනු ඇත, ඒවායේ කේතය නාටකාකාර ලෙස සරල කිරීම සහ නැවත භාවිතා කිරීමේ තවත් මට්ටමක් ඇති කිරීම.
මෙම externalization සාක්ෂාත් කර ගැනීම සඳහා අපි ක්රියාව භාවිත කළ හැකි, bind (>>=)
ඉටු කිරීමටත්, composition
වෙනුවට compose
. එනිසා, එක් ශ්රිතයක නිමැවුමේ සිට තවත් ආදානයකට අගයන් මාරු කිරීම වෙනුවට Bind
එහි M
කොටස පරීක්ෂා Ma
කර සංයුක්ත ශ්රිතය යෙදිය යුතුද සහ කෙසේද යන්න තීරණය කරනු ඇත.a
. ඇත්ත වශයෙන්ම, එහි ව්යුහය පරීක්ෂා කිරීමට සහ අපට අවශ්ය ඕනෑම ආකාරයක යෙදුමක් සිදු කිරීමට හැකිවන පරිදි ශ්රිතය bind
අපගේ විශේෂිත සඳහා විශේෂයෙන් අර්ථ දක්වනු M
ඇත. එසේ වුවද, ආදාන ව්යුහයේ කොටස හුදෙක් පසුකරමින් ඒවා සරල කරන a
බැවින් ඕනෑම දෙයක් විය හැකිය . එබැවින් ...bind
a
අවශ්ය යෙදුම තීරණය කරන විට රචනා කරන ලද ශ්රිතයට නොදැනුවත්වම . මීට අමතරව, රචනා කරන ලද කාර්යයන් සඳහා තවදුරටත් කටයුතු කිරීමට අවශ්ය නොවේM
(a -> Mb) >>= (b -> Mc)
හෝ වඩාත් සංක්ෂිප්තව Mb >>= (b -> Mc)
කෙටියෙන් කිවහොත්, මොනාඩ් බාහිරකරණය වන අතර එමඟින් ආදාන ප්රමාණවත් ලෙස නිරාවරණය වන පරිදි නිර්මාණය කළ පසු ඇතැම් ආදාන අවස්ථා සඳහා ප්රතිකාර කිරීම සඳහා සම්මත හැසිරීම් සපයයි. මෙම සැලසුම අshell and content
ෂෙල් එකෙහි රචනා කරන ලද ශ්රිතයේ යෙදුමට අදාළ දත්ත අඩංගු වන අතර එය ප්රශ්න කරනු ලබන අතර එය bind
ශ්රිතයට පමණක් පවතී .
එබැවින් මොනාඩ් යනු කරුණු තුනකි:
M
පැවැත්වීම සඳහා වු shell අදාළ තොරතුරු monad, bind
කාර්යය අන්තර්ගතය අගය (න්) සඳහා රචනා කාර්යයන් එහි ඉල්ලුම් මෙම ෂෙල් තොරතුරු යොදා ගැනීමට ක්රියාත්මක එය ෂෙල් තුළ සම්බ හා a -> Mb
මොනාඩික් කළමනාකරණ දත්ත ඇතුළත් ප්රති results ල ලබා දීම .පොදුවේ ගත් කල, ශ්රිතයක් සඳහා වන ආදානය එහි ප්රතිදානයට වඩා බෙහෙවින් සීමා කර ඇති අතර එයට දෝෂ තත්වයන් වැනි දේ ඇතුළත් විය හැකිය; එබැවින් ප්රති Mb
result ල ව්යුහය සාමාන්යයෙන් ඉතා ප්රයෝජනවත් වේ. උදාහරණයක් ලෙස, බෙදුම්කරු සිටින විට කොට් operation ාශ ක්රියාකරු අංකයක් ලබා නොදේ 0
.
මීට අමතරව, monad
s හි අගයන් ඔතා, a
මොනාඩික් වර්ගයට Ma
, සහ සාමාන්ය ශ්රිතවලට, a -> b
මොනාඩික් ශ්රිතවලට, a -> Mb
ඒවායේ ප්රති results ල යෙදුමෙන් පසු එතීමෙන් ඇතුළත් කළ හැකිය . ඇත්ත වශයෙන්ම, වැනි bind
, එවැනි එතීමේ කාර්යයන් විශේෂිත වේ M
. උදාහරණයක්:
let return a = [a]
let lift f a = return (f a)
සැලසුම bind
ශ්රිතයේ වෙනස් කළ නොහැකි දත්ත ව්යුහයන් සහ පිරිසිදු ක්රියාකාරිත්වයන් අනුමාන කරන අතර අනෙක් ඒවා සංකීර්ණ වන අතර සහතික කළ නොහැක. එනිසා මොනාඩික් නීති තිබේ:
ලබා දී ඇත ...
M_
return = (a -> Ma)
f = (a -> Mb)
g = (b -> Mc)
ඉන්පසු...
Left Identity : (return a) >>= f === f a
Right Identity : Ma >>= return === Ma
Associative : Ma >>= (f >>= g) === Ma >>= ((fun x -> f x) >>= g)
Associativity
එහි අර්ථය වන්නේ bind
විට නොසලකා ඇගයීම අනුපිළිවෙල ආරක්ෂා bind
ආලේප කරයි. ඒ අර්ථ දැක්වීම තුළ, ය Associativity
වූ parenthesized බලවේගය මුල් ඇගයීම, ඉහත binding
ක f
සහ g
අපේක්ෂා කරන බව පමණක් උත්සවයකට හේතු වනු ඇත Ma
එම සම්පූර්ණ කිරීම සඳහා bind
. එබැවින් Ma
එහි අගය යෙදීමට පෙර ඇගයීම තීරණය කළ යුතු අතර එහි ප්රති f
result ලය අදාළ වේ g
.
මොනාඩ් යනු type ලදායි ලෙස “වර්ගයේ ක්රියාකරු” ආකාරයකි. එය කරුණු තුනක් කරනු ඇත. පළමුව එය එක් වර්ගයක අගයක් වෙනත් වර්ගයකට “ඔතා” (හෝ වෙනත් ආකාරයකින් පරිවර්තනය කරයි) (සාමාන්යයෙන් එය "මොනාඩික් වර්ගයක්" ලෙස හැඳින්වේ). දෙවනුව, එය යටින් පවතින වර්ගයේ සියලුම මෙහෙයුම් (හෝ කාර්යයන්) මොනාඩික් වර්ගයේ ලබා ගත හැකිය. අවසාන වශයෙන් එය සංයුක්ත මොනාඩ් නිපදවීම සඳහා වෙනත් මොනාඩ් සමඟ තම ආත්මය ඒකාබද්ධ කිරීමට සහාය ලබා දෙනු ඇත.
"සමහර විට මොනාඩ්" යනු මූලික වශයෙන් දෘශ්ය මූලික / සී # හි "අහෝසි කළ හැකි වර්ග" වලට සමාන වේ. එය අහෝසි කළ නොහැකි "ටී" වර්ගයක් ගෙන එය "ශුන්ය කළ හැකි <T>" බවට පරිවර්තනය කරයි, ඉන්පසු සියලු ද්විමය ක්රියාකරුවන් විසින් අහෝසි කළ හැකි <T> යන්නෙන් අදහස් කරන්නේ කුමක්ද යන්න නිර්වචනය කරයි.
අතුරු ආබාධ එකවරම නිරූපණය කෙරේ. ශ්රිතයක ප්රතිලාභ අගය සමඟ අතුරු ආබාධ පිළිබඳ විස්තර ඇතුළත් ව්යුහයක් නිර්මාණය වේ. "එසවූ" මෙහෙයුම් පසුව ශ්රිත අතර අගයන් ලබා දෙන බැවින් අතුරු ආබාධ වටා පිටපත් කරයි.
හේතු කිහිපයක් නිසා "වර්ගයේ ක්රියාකරුවන්" පහසුවෙන් වටහා ගත හැකි නමට වඩා ඒවා "මොනාඩ්ස්" ලෙස හැඳින්වේ:
මොනාඩ්ස් සඳහා හොඳ පෙළඹවීමක් වන්නේ සිග්පේ (ඩෑන් පිපෝනි) ගේ මොනාඩ්ස් සොයා ගැනීමට ඔබට හැකි වීමයි! (සමහර විට ඔබට දැනටමත් තිබේ) . ඇත වෙනත් monad නිබන්ධන ගොඩක් misguidedly විවිධ සාම්යයන් භාවිතා වන "සරල පද" තුළ monads පැහැදිලි කිරීමට උත්සාහ කරන බොහෝ දෙනෙක්,: මෙයයි monad නිබන්ධනය පාලිත් ; ඒවායින් වළකින්න.
ඩී.ආර්. මැක් අයිවර් පවසන පරිදි ඔබේ භාෂාව උරා ගන්නේ මන්දැයි අපට කියන්න :
ඉතින්, මම හස්කල් ගැන වෛර කරන දේවල්:
පැහැදිලිව පටන් ගනිමු. මොනාඩ් නිබන්ධන. නැත, මොනාඩ්ස් නොවේ. විශේෂයෙන් නිබන්ධන. ඔවුන් නිමක් නැති, අධික ලෙස පිපිරී සිටින අතර ආදරණීය දෙවියන් ඔවුන් වෙහෙසකරයි. තවද, ඔවුන් සැබවින්ම උදව් කරන බවට ඒත්තු ගැන්වෙන සාක්ෂි මා දැක නැත. පන්ති අර්ථ දැක්වීම කියවන්න, යම් කේතයක් ලියන්න, බියජනක නම ඉක්මවා යන්න.
ඔයා කියනවා ඔයාට මොනාඩ් තේරෙනවා ඇති කියලා? හොඳයි, ඔබ යන ගමන. වෙනත් මොනාඩ් භාවිතා කිරීම අරඹන්න, පොදුවේ මොනාඩ්ස් යනු කුමක්දැයි ඉක්මනින් හෝ පසුව ඔබට වැටහෙනු ඇත.
[ඔබ ගණිතමය වශයෙන් නැඹුරු නම්, ඔබට නිබන්ධන දුසිම් ගණනක් නොසලකා හැර අර්ථ දැක්වීම ඉගෙන ගැනීමට අවශ්ය විය හැකිය, නැතහොත් කාණ්ඩ න්යායේ දේශන අනුගමනය කරන්න . :) අර්ථ දැක්වීම ප්රධාන කොටසක් Monad එම් එක් එක් සඳහා නිර්වචනය කරන බව "වර්ගය ඉදිකිරීමටත්" ඇතුළත් වන බව ය පවත්නා වර්ගය "ටී" නව වර්ගයේ "එම්ටී", සහ "සාමාන්ය" වර්ග සහ "එම්" වර්ග අතර ඉදිරියට සහ පසුපසට යාමට ක්රම කිහිපයක්.]
එසේම, පුදුමයට කරුණක් නම්, මොනාඩ්ස් සඳහා හොඳම හැඳින්වීමක් වන්නේ ඇත්ත වශයෙන්ම මොනාඩ්ස් හඳුන්වා දෙන මුල් කාලීන අධ්යයන පත්රිකාවලින් එකක් වන ක්රියාකාරී වැඩසටහන් සඳහා පිලිප් වැඩ්ලර්ගේ මොනාඩ්ස් ය . එහි ඇති බොහෝ කෘතිම නිබන්ධන මෙන් නොව එය සැබවින්ම ප්රායෝගික, සුළු නොවන අභිප්රේරණ උදාහරණ ඇත.
මොනාඩ්ස් යනු දත්ත වලට වියුක්ත දත්ත වර්ග මොනවාද යන්න ප්රවාහය පාලනය කිරීමයි.
වෙනත් වචන වලින් කිවහොත්, බොහෝ සංවර්ධකයින් කට්ටල, ලැයිස්තු, ශබ්ද කෝෂ (හෝ හැෂ්, හෝ සිතියම්) සහ ගස් පිළිබඳ අදහස සමඟ සැපපහසු වේ. එම දත්ත වර්ග තුළ විශේෂ අවස්ථා රාශියක් ඇත (නිදසුනක් ලෙස InsertionOrderPreservingIdentityHashMap).
කෙසේ වෙතත්, ක්රමලේඛ “ප්රවාහයට” මුහුණ දෙන විට, බොහෝ සංවර්ධකයින්, ස්විචය / නඩුව, කරන්න, ගොටෝ (grr) සහ (සමහර විට) වසා දැමීම් වලට වඩා බොහෝ ඉදිකිරීම් වලට නිරාවරණය වී නොමැත.
ඉතින්, මොනාඩ් යනු හුදෙක් පාලක ප්රවාහ ඉදිකිරීමකි. මොනාඩ් වෙනුවට ආදේශ කිරීමට වඩා හොඳ වාක්ය ඛණ්ඩයක් වනුයේ 'පාලන වර්ගය' ය.
එනිසා, මොනාඩ් එකකට පාලන තර්කනය, හෝ ප්රකාශ හෝ කාර්යයන් සඳහා තව් ඇත - දත්ත ව්යුහයන්ට සමාන වන්නේ සමහර දත්ත ව්යුහයන් මඟින් ඔබට දත්ත එකතු කිරීමට සහ එය ඉවත් කිරීමට ඉඩ සලසයි.
උදාහරණයක් ලෙස, "if" monad:
if( clause ) then block
එහි සරලම ස්ථානයට තව් දෙකක් ඇත - වගන්තියක් සහ බ්ලොක් එකක්. මෙම if
monad සාමාන්යයෙන් වගන්තිය ප්රතිඵලයක් ඇගයීමට ඉදිකර ඇත, හා බොරු නොවේ නම්, වාරණ ඇගයීමට. බොහෝ සංවර්ධකයින් මොනාඩ් වලට 'නම්' ඉගෙන ගන්නා විට හඳුන්වා නොදෙන අතර effective ලදායී තර්කනය ලිවීමට මොනාඩ්ස් තේරුම් ගැනීම අවශ්ය නොවේ.
දත්ත ව්යුහයන් වඩාත් සංකීර්ණ විය හැකි ආකාරයටම මොනාඩ්ස් වඩාත් සංකීර්ණ විය හැකි නමුත් සමාන අර්ථකථන තිබිය හැකි නමුත් විවිධාකාර ක්රියාත්මක කිරීම් සහ වාක්ය ඛණ්ඩයන් ඇති මොනාඩ්හි පුළුල් කාණ්ඩ රාශියක් ඇත.
ඇත්ත වශයෙන්ම, දත්ත ව්යුහයන් නැවත නැවත සිදු කළ හැකි හෝ ගමන් කළ හැකි ආකාරයටම, මොනාඩ්ස් ඇගයීමට ලක් කළ හැකිය.
පරිශීලකයින් විසින් නිර්වචනය කරන ලද මොනාඩ් සඳහා සම්පාදකයින්ට සහය තිබිය හැකිය. හස්කල් නිසැකවම එසේ කරයි. මොනාඩ් යන වචනය භාෂාවෙන් භාවිතා නොකලද අයෝක්ට සමාන හැකියාවන් ඇත.
මගේ ප්රියතම මොනාඩ් නිබන්ධනය:
http://www.haskell.org/haskellwiki/All_About_Monads
("මොනාඩ් නිබන්ධනය" සඳහා ගූගල් සෙවුමක ඇති පහර 170,000 න්!)
@ ස්ටූ: මොනාඩ්ස්හි ලක්ෂ්යය නම් පිරිසිදු කේතයට (සාමාන්යයෙන්) අනුක්රමික අර්ථකථන එක් කිරීමට ඉඩ දීමයි; ඔබට මොනාඩ්ස් රචනා කළ හැකිය (මොනාඩ් ට්රාන්ස්ෆෝමර් භාවිතා කරමින්) සහ දෝෂ හැසිරවීම, හවුල් තත්වය සහ ලොග් වීම වැනි විග්රහ කිරීම වැනි වඩාත් රසවත් හා සංකීර්ණ ඒකාබද්ධ අර්ථකථන ලබා ගත හැකිය. මේ සියල්ල පිරිසිදු කේතයකින් කළ හැකි අතර, මොනාඩ්ස් ඔබට එය වියුක්ත කර මොඩියුලර් පුස්තකාලවල නැවත භාවිතා කිරීමට ඉඩ දෙයි (වැඩසටහන්කරණයේ සෑම විටම හොඳයි) මෙන්ම එය අත්යවශ්ය යැයි පෙනෙන පරිදි පහසු වාක්ය ඛණ්ඩයක් සපයයි.
හැස්කෙල් සතුව දැනටමත් ක්රියාකරු අධි බර පැටවීමක් ඇත [1]: එය ජාවා හෝ සී # හි අතුරුමුහුණත් භාවිතා කරන ආකාරයටම පන්ති වර්ග භාවිතා කරයි, නමුත් හැස්කෙල් සිදුවන්නේ + && සහ> වැනි අක්ෂරාංක නොවන ටෝකන වලට අනන්යතා හඳුනාගැනීම් ලෙස ඉඩ දීමයි. ඔබ "අර්ධ සළකුණ අධික ලෙස පැටවීම" අදහස් කරන්නේ නම් එය ඔබ දෙස බලන ආකාරයට ක්රියාකරු අධික ලෙස පැටවීම පමණි [2]. එය කළු මැජික් මෙන් පෙනෙන අතර "අර්ධ සළකුණ අධික ලෙස පැටවීම" සඳහා කරදරයක් ඉල්ලා සිටී (පින්තූර ව්යවසායක පර්ල් හැකර්වරු මෙම අදහසට හසුවීම) නමුත් කාරණය වන්නේ මොනාඩ්ස් නොමැතිව .
මේ සියල්ල අවශ්ය ප්රමාණයට වඩා බෙහෙවින් සංකීර්ණ ය. සිග්පේගේ ලිපිය ඉතා සිසිල් නමුත් එය පැහැදිලි කිරීම සඳහා හස්කල් භාවිතා කරයි, මොස්කස් ග්රහණය කර ගැනීමට හස්කල් තේරුම් ගැනීම සහ මොස්කැඩ් ග්රාස් කිරීමට හස්කල් තේරුම් ගැනීම පිළිබඳ කුකුළු මස් හා බිත්තර ගැටලුව බිඳ දැමීමට කුමන ආකාරයේ අසමත් ද?
[1] මෙය මොනාඩ්ස් වලින් වෙනම ගැටළුවක් වන නමුත් මොනාඩ්ස් විසින් හස්කල්ගේ ක්රියාකරු අධි බර පැටවීමේ අංගය භාවිතා කරයි.
[2] මොනාඩික් ක්රියාවන් දම්වැලෙහි ක්රියාකරු >> = (උච්චාරණය කරන ලද “බන්ධනය”) වන බැවින් මෙය ද සරල කිරීමකි, නමුත් වරහන් සහ අර්ධ සළකුණු සහ / හෝ ඉන්ඩෙන්ටේෂන් සහ නව රේඛා භාවිතා කිරීමට ඔබට ඉඩ සලසන සින්ටැක්ටික් සීනි (“කරන්න”) ඇත.
මම මොනාඩ්ස් ගැන වෙනස් ආකාරයකින් සිතමින් සිටිමි. මම ඒවා ගණිතමය ආකාරයකින් ක්රියාත්මක කිරීමේ අනුපිළිවෙල වියුක්ත කිරීමක් ලෙස සිතමින් සිටිමි, එමඟින් නව ආකාරයේ බහුමාපක ලබා ගත හැකිය.
ඔබ අත්යවශ්ය භාෂාවක් භාවිතා කරන්නේ නම් සහ ඔබ යම් ප්රකාශන පිළිවෙලට ලියන්නේ නම්, සෑම විටම කේතය හරියටම එම අනුපිළිවෙලට ක්රියාත්මක වේ.
සරල අවස්ථාවෙහිදී, ඔබ මොනාඩ් භාවිතා කරන විට, එය එසේම දැනේ - අනුපිළිවෙලින් සිදුවන ප්රකාශන ලැයිස්තුවක් ඔබ අර්ථ දක්වයි. ඒ හැර, ඔබ භාවිතා කරන මොනෑඩය මත පදනම්ව, ඔබේ කේතය පිළිවෙලින් (IO මොනාඩ් මෙන්) ක්රියාත්මක විය හැකිය, එකවර අයිතම කිහිපයකට සමාන්තරව (ලැයිස්තු මොනාඩ් වැනි), එය අර්ධ වශයෙන් නතර විය හැකිය (සමහර විට මොනාඩ් වැනි) , එය නැවත ආරම්භ කිරීම සඳහා අර්ධ වශයෙන් විරාමයක් තැබිය හැකිය (නැවත ආරම්භ කිරීමේ මොනාඩ් එකක මෙන්), එය නැවත පෙරළා ආරම්භ කළ හැකිය (ගනුදෙනු මොනාඩ් වැනි), හෝ වෙනත් විකල්පයන් උත්සාහ කිරීම සඳහා එය අර්ධ වශයෙන් පෙරළා දැමිය හැකිය (ලොජික් මොනාඩ් වැනි) .
මොනාඩ්ස් බහුමාමක බැවින්, ඔබේ අවශ්යතා අනුව එකම කේතය විවිධ මොනාඩ් වල ධාවනය කළ හැකිය.
ප්ලස්, සමහර අවස්ථාවල, එකවර බහු විශේෂාංග ලබා ගැනීම සඳහා මොනාඩ්ස් (මොනාඩ් ට්රාන්ස්ෆෝමර් සමඟ) ඒකාබද්ධ කළ හැකිය.
මම තවමත් මොනාඩ්ස් වලට අලුත් ය, නමුත් කියවීමට හොඳ යැයි හැඟෙන සබැඳියක් බෙදා ගැනීමට මම සිතුවෙමි (පින්තූර සමඟ !!): http://www.matusiak.eu/numerodix/blog/2012/3/11/ monads-for-the-layman / (අනුබද්ධයක් නැත)
මූලික වශයෙන්, ලිපියෙන් මට ලැබුණු උණුසුම් හා නොපැහැදිලි සංකල්පය නම්, මොනාඩ්ස් යනු මූලික වශයෙන් අසමාන ශ්රිතයන් සංයුක්ත ආකාරයකින් වැඩ කිරීමට ඉඩ සලසන ඇඩැප්ටරයන් වන සංකල්පයයි, එනම් නොගැලපෙන ප්රතිලාභ ගැන කරදර නොවී විවිධ කාර්යයන් පෙළගැස්වීමට හා ඒවා ගැලපීමට හැකි වීමයි. වර්ග සහ එවැනි. ඉතින් අපි මෙම ඇඩප්ටර සෑදීමට උත්සාහ කරන විට ඇපල් හා දොඩම් දොඩම් සමඟ ඇපල් තබා ගැනීම BIND ශ්රිතය භාරව පවතී. තවද LIFT ශ්රිතය "පහළ මට්ටමේ" කාර්යයන් භාර ගැනීම සහ ඒවා BIND ශ්රිත සමඟ වැඩ කිරීම සඳහා "වැඩිදියුණු කිරීම" සහ සංයුක්ත විය යුතුය.
මම එය නිවැරදිව තේරුම් ගත්තා යැයි මම විශ්වාස කරමි, වඩා වැදගත් ලෙස, ලිපියට මොනාඩ්ස් පිළිබඳ වලංගු මතයක් ඇතැයි බලාපොරොත්තු වෙමි. වෙන කිසිවක් නොමැති නම්, මෙම ලිපිය මොනාඩ්ස් ගැන වැඩිදුර ඉගෙන ගැනීමට ඇති මගේ රුචිය වැඩි කිරීමට උපකාරී විය.
ඉහත විශිෂ්ට පිළිතුරු වලට අමතරව, ජාවාස්ක්රිප්ට් පුස්තකාල jQuery සමඟ සංකල්පය සම්බන්ධ කිරීම මගින් මොනාඩ්ස් පැහැදිලි කරන ඊළඟ ලිපියට (පැට්රික් තොම්සන් විසින්) සබැඳියක් ඉදිරිපත් කරමි (සහ DOM හැසිරවීමට “ක්රම දාමය” භාවිතා කරන ආකාරය) : jQuery යනු මොනාඩ් ය
මෙම jQuery ප්රලේඛනය ම "monad" යන වචනය යොමු එහෙත් "තනන්නා රටාව" බොහෝ විට හුරු පුරුදු වන ගැන සාකච්ඡා කරන්නේ නැත. මෙය ඔබ නොදැනුවත්වම නිසි මොනාඩ් එකක් ඇති බව වෙනස් නොකරයි.
මොනාඩ්ස් යනු රූපක නොවේ , නමුත් ඩැනියෙල් ස්පීවාක් පැහැදිලි කරන පරිදි, පොදු රටාවකින් මතුවන ප්රායෝගිකව ප්රයෝජනවත් වියුක්තයකි.
මොනාඩ් යනු පොදු සන්දර්භයක් බෙදා ගන්නා ගණනය කිරීම් එකට ඒකාබද්ධ කිරීමේ ක්රමයකි. එය හරියට පයිප්ප ජාලයක් තැනීම හා සමානයි. ජාලය තැනීමේදී, ඒ හරහා දත්ත ගලා එන්නේ නැත. නමුත් මම සියලු බිටු 'බයින්ඩ්' සහ 'ආපසු' සමඟ කොටස් කිරීම අවසන් කළ පසු, මම එවැනි දෙයක් ඉල්ලා runMyMonad monad data
සිටින අතර දත්ත පයිප්ප හරහා ගලා යයි.
ප්රායෝගිකව, මොනාඩ් යනු ක්රියාකාරී සංයුති ක්රියාකරුගේ අභිරුචි ක්රියාත්මක කිරීමක් වන අතර එය අතුරු ආබාධ සහ නොගැලපෙන ආදාන සහ ප්රතිලාභ අගයන් (දම්වැල සඳහා) බලා ගනී.
{-# LANGUAGE InstanceSigs #-}
newtype Id t = Id t
instance Monad Id where
return :: t -> Id t
return = Id
(=<<) :: (a -> Id b) -> Id a -> Id b
f =<< (Id x) = f x
$
කාර්යයන් වල යෙදුම් ක්රියාකරු
forall a b. a -> b
කැනොනිකල් ලෙස අර්ථ දක්වා ඇත
($) :: (a -> b) -> a -> b
f $ x = f x
infixr 0 $
හස්කල්-ප්රාථමික ශ්රිත යෙදුම f x
( infixl 10
) අනුව.
සංයුතිය .
අර්ථ දැක්වෙන්නේ$
ලෙස
(.) :: (b -> c) -> (a -> b) -> (a -> c)
f . g = \ x -> f $ g x
infixr 9 .
සහ සමානකම් තෘප්තිමත් කරයි forall f g h.
f . id = f :: c -> d Right identity
id . g = g :: b -> c Left identity
(f . g) . h = f . (g . h) :: a -> d Associativity
.
සහායක වන අතර id
එය එහි දකුණු හා වම් අනන්යතාවය වේ.
ක්රමලේඛනයේදී, මොනාඩ් යනු මොනාඩ් වර්ගයේ පන්තියේ නිදසුනක් සහිත ෆන්ක්ටර් වර්ගයේ ඉදිකිරීම්කරුවෙකි. අර්ථ දැක්වීමේ හා ක්රියාත්මක කිරීමේ සමාන ප්රභේද කිහිපයක් ඇත, සෑම එකක්ම මොනාඩ් වියුක්තකරණය පිළිබඳ තරමක් වෙනස් ප්රතිභාවයන් දරයි.
ඒ functor වර්ගයක් ඉදිකිරීමටත් වේ f
ආකාරයේ * -> *
ඇති functor වර්ගය පන්තියේ උදාහරණයක් සමග.
{-# LANGUAGE KindSignatures #-}
class Functor (f :: * -> *) where
map :: (a -> b) -> (f a -> f b)
ස්ථිතිකව බලාත්මක කරන ලද වර්ගයේ ප්රොටෝකෝලය අනුගමනය කිරීමට අමතරව, ෆන්ක්ටර් වර්ගයේ පන්තියේ අවස්ථා වීජීය ෆන්ක්ටර් නීතිවලට අවනත විය යුතුය forall f g.
map id = id :: f t -> f t Identity
map f . map g = map (f . g) :: f a -> f c Composition / short cut fusion
ක්රියාකාරී ගණනය කිරීම් වල වර්ගය ඇත
forall f t. Functor f => f t
ගණනය කිරීම සන්දර්භය තුළ ප්රති results ල c r
වලින් සමන්විත වේ . r
c
ඒකීය මොනාඩික් ශ්රිත හෝ ක්ලයිස්ලි ඊතල වල වර්ගය ඇත
forall m a b. Functor m => a -> m b
Kleisi ඊතල එක් තර්කයක් ගෙන ක්රියාත්මක වන බව ය a
සහ monadic ගණනය නැවතm b
.
ක්ලයිස්ලි ත්රිත්වයට අනුව මොනාඩ්ස් කැනොනිකල් ලෙස අර්ථ දක්වා ඇත forall m. Functor m =>
(m, return, (=<<))
වර්ගය පන්තිය ලෙස ක්රියාත්මක කරයි
class Functor m => Monad m where
return :: t -> m t
(=<<) :: (a -> m b) -> m a -> m b
infixr 1 =<<
මෙම Kleisli අනන්යතාව return
අගය ප්රවර්ධනය කරන Kleisli ඊතලය t
monadic සන්දර්භය බවට m
. විස්තාරණය හෝ ක්ලයිස්ලි යෙදුම ගණනය =<<
කිරීමේ ප්රති a -> m b
results ල සඳහා ක්ලයිස්ලි ඊතලයක් යොදයි m a
.
ක්ලයිස්ලි සංයුතිය දීර් <=<
extension කිරීම අනුව අර්ථ දැක්වේ
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> (a -> m c)
f <=< g = \ x -> f =<< g x
infixr 1 <=<
<=<
ක්ලයිස්ලි ඊතල දෙකක් රචනා කරයි, දකුණු ඊතලයේ යෙදුමේ ප්රති results ල සඳහා වම් ඊතලය යොදන්න.
මොනාඩ් වර්ගයේ පන්තියේ අවස්ථා මොනාඩ් නීතිවලට අවනත විය යුතුය , ක්ලයිස්ලි සංයුතිය අනුව වඩාත් අලංකාර ලෙස ප්රකාශ කර ඇත:forall f g h.
f <=< return = f :: c -> m d Right identity
return <=< g = g :: b -> m c Left identity
(f <=< g) <=< h = f <=< (g <=< h) :: a -> m d Associativity
<=<
සහායක වන අතර return
එය එහි දකුණු හා වම් අනන්යතාවය වේ.
අනන්යතා වර්ගය
type Id t = t
යනු වර්ග මත අනන්යතා ශ්රිතයයි
Id :: * -> *
විනෝදකාමී ලෙස අර්ථකථනය,
return :: t -> Id t
= id :: t -> t
(=<<) :: (a -> Id b) -> Id a -> Id b
= ($) :: (a -> b) -> a -> b
(<=<) :: (b -> Id c) -> (a -> Id b) -> (a -> Id c)
= (.) :: (b -> c) -> (a -> b) -> (a -> c)
කැනොනිකල් හස්කල් හි, අනන්යතා මොනාඩ් අර්ථ දක්වා ඇත
newtype Id t = Id t
instance Functor Id where
map :: (a -> b) -> Id a -> Id b
map f (Id x) = Id (f x)
instance Monad Id where
return :: t -> Id t
return = Id
(=<<) :: (a -> Id b) -> Id a -> Id b
f =<< (Id x) = f x
විකල්ප වර්ගයක්
data Maybe t = Nothing | Just t
ප්රති Maybe t
result ලයක් අවශ්ය නොවන ගණනය කිරීම සංකේතවත් කරයි t
, ගණනය කිරීම “අසමත්” විය හැකිය. මොනාඩ් විකල්පය අර්ථ දක්වා ඇත
instance Functor Maybe where
map :: (a -> b) -> (Maybe a -> Maybe b)
map f (Just x) = Just (f x)
map _ Nothing = Nothing
instance Monad Maybe where
return :: t -> Maybe t
return = Just
(=<<) :: (a -> Maybe b) -> Maybe a -> Maybe b
f =<< (Just x) = f x
_ =<< Nothing = Nothing
a -> Maybe b
ප්රති result ලයකට අදාළ වන්නේ ප්රති .ලයක් ලැබෙන්නේ නම් පමණි Maybe a
.
newtype Nat = Nat Int
ස්වාභාවික සංඛ්යා ශුන්යයට වඩා වැඩි හෝ සමාන සංඛ්යාවක් ලෙස සංකේතවත් කළ හැකිය.
toNat :: Int -> Maybe Nat
toNat i | i >= 0 = Just (Nat i)
| otherwise = Nothing
අඩු කිරීම යටතේ ස්වාභාවික සංඛ්යා වසා නැත.
(-?) :: Nat -> Nat -> Maybe Nat
(Nat n) -? (Nat m) = toNat (n - m)
infixl 6 -?
මොනාඩ් විකල්පය ව්යතිරේක හැසිරවීමේ මූලික ආකාරයක් ආවරණය කරයි.
(-? 20) <=< toNat :: Int -> Maybe Nat
ලැයිස්තු මොනාඩ්, ලැයිස්තු වර්ගයට ඉහළින්
data [] t = [] | t : [t]
infixr 5 :
සහ එහි ආකලන මොනොයිඩ් ක්රියාකාරිත්වය “එකතු කරන්න”
(++) :: [t] -> [t] -> [t]
(x : xs) ++ ys = x : xs ++ ys
[] ++ ys = ys
infixr 5 ++
සංකේතවත් එකක් අනිකට සම්බන්ධව ගණනය [t]
ස්වභාවික ප්රමාණය උපයාගන්නා 0, 1, ...
ප්රතිඵල t
.
instance Functor [] where
map :: (a -> b) -> ([a] -> [b])
map f (x : xs) = f x : map f xs
map _ [] = []
instance Monad [] where
return :: t -> [t]
return = (: [])
(=<<) :: (a -> [b]) -> [a] -> [b]
f =<< (x : xs) = f x ++ (f =<< xs)
_ =<< [] = []
දීර්ඝ =<<
concatenates ++
සියලු ලැයිස්තු [b]
අයදුම්පත් ප්රතිඵලයක් f x
වන Kleisli ඊතලය a -> [b]
අංග කිරීමට [a]
තනි ප්රතිඵලයක් ලැයිස්තුවට [b]
.
ධනාත්මක නිඛිලයක නිසි බෙදුම්කරුවන් විය n
යුතුය
divisors :: Integral t => t -> [t]
divisors n = filter (`divides` n) [2 .. n - 1]
divides :: Integral t => t -> t -> Bool
(`divides` n) = (== 0) . (n `rem`)
එවිට
forall n. let { f = f <=< divisors } in f n = []
මොනාඩ් වර්ගයේ පන්තිය නිර්වචනය කිරීමේදී, දිගුව වෙනුවට =<<
, හස්කල් ප්රමිතිය එහි ෆ්ලිප්, බන්ධන ක්රියාකරු භාවිතා කරයි >>=
.
class Applicative m => Monad m where
(>>=) :: forall a b. m a -> (a -> m b) -> m b
(>>) :: forall a b. m a -> m b -> m b
m >> k = m >>= \ _ -> k
{-# INLINE (>>) #-}
return :: a -> m a
return = pure
සරල බව වෙනුවෙන්, මෙම පැහැදිලි කිරීම පන්තියේ ධූරාවලිය භාවිතා කරයි
class Functor f
class Functor m => Monad m
හස්කල් හි වර්තමාන සම්මත ධූරාවලිය වේ
class Functor f
class Functor p => Applicative p
class Applicative m => Monad m
මක්නිසාද යත් සෑම මොනාඩ් එකක්ම විනෝදකාමියෙකු පමණක් නොව, සෑම අයදුම්කරුවෙකුම විනෝදකාමී වන අතර සෑම මොනාඩ් එකක්ම අයදුම්කරුවෙකි.
අත්යවශ්ය මොනෝඩ් නම් ලැයිස්තුව භාවිතා කිරීම
for a in (1, ..., 10)
for b in (1, ..., 10)
p <- a * b
if even(p)
yield p
දළ වශයෙන් ඩූ බ්ලොක් වෙත පරිවර්තනය වේ ,
do a <- [1 .. 10]
b <- [1 .. 10]
let p = a * b
guard (even p)
return p
සමාන මොනාඩ් අවබෝධය ,
[ p | a <- [1 .. 10], b <- [1 .. 10], let p = a * b, even p ]
සහ ප්රකාශනය
[1 .. 10] >>= (\ a ->
[1 .. 10] >>= (\ b ->
let p = a * b in
guard (even p) >> -- [ () | even p ] >>
return p
)
)
අංකනය සහ මොනාඩ් අවබෝධය යනු කූඩු බන්ධන ප්රකාශන සඳහා සින්ටැක්ටික් සීනි වේ. මොනාඩික් ප්රති .ල වල දේශීය නම බන්ධනය සඳහා බන්ධන ක්රියාකරු භාවිතා කරයි.
let x = v in e = (\ x -> e) $ v = v & (\ x -> e)
do { r <- m; c } = (\ r -> c) =<< m = m >>= (\ r -> c)
කොහෙද
(&) :: a -> (a -> b) -> b
(&) = flip ($)
infixl 0 &
ආරක්ෂක කාර්යය අර්ථ දක්වා ඇත
guard :: Additive m => Bool -> m ()
guard True = return ()
guard False = fail
එහිදී ඒකක වර්ගය හෝ “හිස් ටුපල්”
data () = ()
තේරීම සහ අසාර්ථකත්වය සඳහා සහාය වන ආකලන මොනාඩ් වර්ග වර්ගයක් භාවිතා කිරීමෙන් වියුක්ත කළ හැකිය
class Monad m => Additive m where
fail :: m t
(<|>) :: m t -> m t -> m t
infixl 3 <|>
instance Additive Maybe where
fail = Nothing
Nothing <|> m = m
m <|> _ = m
instance Additive [] where
fail = []
(<|>) = (++)
එහිදී fail
හා <|>
එය අවයවය පිහිටුවීමටforall k l m.
k <|> fail = k
fail <|> l = l
(k <|> l) <|> m = k <|> (l <|> m)
සහ fail
ආකලන මොනාඩ් වල ශුන්ය මූලද්රව්යය අවශෝෂණය / විනාශ කිරීම වේ
_ =<< fail = fail
ඇතුලත නම්
guard (even p) >> return p
even p
සත්ය නම්, එවිට ආරක්ෂකයා [()]
විසින් >>
දේශීය නියත ශ්රිතය නිපදවන අතර අර්ථ දැක්වීම අනුව
\ _ -> return p
ප්රති .ලයට අදාළ වේ ()
. අසත්ය නම්, ආරක්ෂකයා විසින් මොනාඩ්ගේ fail
( []
) ලැයිස්තුව නිපදවන අතර , එය ක්ලයිස්ලි ඊතලයක් යෙදීම සඳහා කිසිදු ප්රති result ලයක් ලබා නොදේ >>
, එබැවින් මෙය p
මඟ හැරේ.
කුප්රකට ලෙස, රාජ්ය ගණනය කිරීම් කේතනය කිරීම සඳහා මොනාඩ්ස් භාවිතා කරයි.
ඒ රාජ්ය සකසනය ශ්රිතයක් වේ
forall st t. st -> (t, st)
එය රාජ්යයක් සංක්රමණය කර st
ප්රති .ලයක් ලබා දෙයි t
. මෙම රාජ්ය st
දෙයක් විය හැක. කිසිවක්, ධජය, ගණන් කිරීම, අරාව, හැසිරවීම, යන්ත්රය, ලෝකය.
රාජ්ය සකසන වර්ගය සාමාන්යයෙන් හැඳින්වේ
type State st t = st -> (t, st)
රාජ්ය සකසනය monad මෙම kinded වේ * -> *
functor State st
. රාජ්ය සකසනය මොනාඩ් හි ක්ලයිස්ලි ඊතල යනු කාර්යයන් ය
forall st a b. a -> (State st) b
කැනොනිකල් හස්කල් හි, රාජ්ය ප්රොසෙසර් මොනාඩ් හි කම්මැලි අනුවාදය අර්ථ දක්වා ඇත
newtype State st t = State { stateProc :: st -> (t, st) }
instance Functor (State st) where
map :: (a -> b) -> ((State st) a -> (State st) b)
map f (State p) = State $ \ s0 -> let (x, s1) = p s0
in (f x, s1)
instance Monad (State st) where
return :: t -> (State st) t
return x = State $ \ s -> (x, s)
(=<<) :: (a -> (State st) b) -> (State st) a -> (State st) b
f =<< (State p) = State $ \ s0 -> let (x, s1) = p s0
in stateProc (f x) s1
ආරම්භක තත්වයක් සැපයීමෙන් රාජ්ය සකසනයක් ක්රියාත්මක වේ:
run :: State st t -> st -> (t, st)
run = stateProc
eval :: State st t -> st -> t
eval = fst . run
exec :: State st t -> st -> st
exec = snd . run
රාජ්ය ප්රවේශය සපයනු ලබන්නේ ප්රාථමිකයන් get
සහ put
, රාජ්ය මොනාඩ් වලට වඩා වියුක්ත කිරීමේ ක්රම :
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
class Monad m => Stateful m st | m -> st where
get :: m st
put :: st -> m ()
m -> st
මොනාඩ් මත රාජ්ය වර්ගයේ ක්රියාකාරී යැපීමක් ප්රකාශ කරයි ; a , උදාහරණයක් ලෙස, රාජ්ය වර්ගය අද්විතීය ලෙස තීරණය කරයි .st
m
State t
t
instance Stateful (State st) st where
get :: State st st
get = State $ \ s -> (s, s)
put :: st -> State st ()
put s = State $ \ _ -> ((), s)
void
C ට සමාන ලෙස භාවිතා කරන ඒකක වර්ගය සමඟ .
modify :: Stateful m st => (st -> st) -> m ()
modify f = do
s <- get
put (f s)
gets :: Stateful m st => (st -> t) -> m t
gets f = do
s <- get
return (f s)
gets
බොහෝ විට වාර්තා ක්ෂේත්ර ප්රවේශයන් සමඟ භාවිතා කරයි.
විචල්ය නූල් වලට සමාන රාජ්ය මොනාඩ්
let s0 = 34
s1 = (+ 1) s0
n = (* 12) s1
s2 = (+ 7) s1
in (show n, s2)
එහිදී s0 :: Int
, සමානව යොමු විනිවිද පෙනෙන, නමුත් අසීමිත ලෙස වඩා අලංකාර සහ ප්රායෝගික වේ
(flip run) 34
(do
modify (+ 1)
n <- gets (* 12)
modify (+ 7)
return (show n)
)
modify (+ 1)
වර්ගය ගණනය කිරීමකි State Int ()
, එහි බලපෑම සමාන වේ return ()
.
(flip run) 34
(modify (+ 1) >>
gets (* 12) >>= (\ n ->
modify (+ 7) >>
return (show n)
)
)
ඇසෝසියේටිව් මොනාඩ් නියමය අනුව ලිවිය හැකිය >>=
forall m f g.
(m >>= f) >>= g = m >>= (\ x -> f x >>= g)
හෝ
do { do { do {
r1 <- do { x <- m; r0 <- m;
r0 <- m; = do { = r1 <- f r0;
f r0 r1 <- f x; g r1
}; g r1 }
g r1 }
} }
ප්රකාශන-නැඹුරු වැඩසටහන්කරණයේදී (උදා: රස්ට්), බ්ලොක් එකක අවසාන ප්රකාශය එහි අස්වැන්න නියෝජනය කරයි. බන්ධන ක්රියාකරු සමහර විට “ක්රමලේඛගත කළ හැකි අර්ධ සළකුණක්” ලෙස හැඳින්වේ.
පුනරාවර්තන පාලන ව්යුහය ව්යුහාත්මක අත්යවශ්ය ක්රමලේඛනවල ප්රාථමිකයන් ඒකාකාරී ලෙස අනුකරණය කරනු ලැබේ
for :: Monad m => (a -> m b) -> [a] -> m ()
for f = foldr ((>>) . f) (return ())
while :: Monad m => m Bool -> m t -> m ()
while c m = do
b <- c
if b then m >> while c m
else return ()
forever :: Monad m => m t
forever m = m >> forever m
data World
I / O ලෝක රාජ්ය ප්රොසෙසර් මොනාඩ් යනු පිරිසිදු හස්කල්ගේ සහ සැබෑ ලෝකයේ ප්රතිසන්ධානයකි. සත්ය වශයෙන්ම දැඩි ලෙස ක්රියාත්මක කිරීම පිළිබඳ සමීප ප්රතිසමයක්:
type IO t = World -> (t, World)
අපිරිසිදු ප්රාථමිකයන් විසින් අන්තර්ක්රියාකාරිත්වයට පහසුකම් සපයයි
getChar :: IO Char
putChar :: Char -> IO ()
readFile :: FilePath -> IO String
writeFile :: FilePath -> String -> IO ()
hSetBuffering :: Handle -> BufferMode -> IO ()
hTell :: Handle -> IO Integer
. . . . . .
IO
ප්රාථමිකයන් භාවිතා කරන කේතයේ අපිරිසිදුකම වර්ග පද්ධතිය මඟින් ස්ථිරවම ප්රොටොකෝලය කරනු ලැබේ. සංශුද්ධතාවය නියමයි, සිදුවන්නේ කුමක්ද IO
, රැඳී පවතී IO
.
unsafePerformIO :: IO t -> t
නැතහොත්, අවම වශයෙන්, කළ යුතුය.
හැස්කල් වැඩසටහනක වර්ගයේ අත්සන
main :: IO ()
main = putStrLn "Hello, World!"
දක්වා පුළුල් වේ
World -> ((), World)
ලෝකයක් පරිවර්තනය කරන ශ්රිතයක්.
වස්තූන් කුමන වර්ගයට අයත්ද යන්න හැස්කල් වර්ග වන අතර හස්කල් වර්ග අතර ක්රියාකාරිත්වයන් වන්නේ “වේගවත් හා ලිහිල්” කාණ්ඩයයි Hask
.
ඒ functor T
ප්රවර්ගයක් සිට සිතියම් වේ C
ප්රවර්ග සඳහා D
; තුළ C
ඇති වස්තුවක එක් එක් වස්තුව සඳහාD
Tobj : Obj(C) -> Obj(D)
f :: * -> *
සහ එක් මෝෆිස් C
සඳහාD
Tmor : HomC(X, Y) -> HomD(Tobj(X), Tobj(Y))
map :: (a -> b) -> (f a -> f b)
කොහේද X
, Y
වස්තූන් ඇත C
. HomC(X, Y)
යනු homomorphism පන්තියේ සියලු morphisms ක X -> Y
දී C
. දී “ව්යුහය” තුළ C
, මෝෆිස් අනන්යතාවය සහ සංයුතිය ෆන්ක්ටර් විසින් ආරක්ෂා කළ යුතුය D
.
Tmor Tobj
T(id) = id : T(X) -> T(X) Identity
T(f) . T(g) = T(f . g) : T(X) -> T(Z) Composition
මෙම Kleisli ප්රවර්ගය ප්රවර්ග ක C
වන Kleisli ත්රිත්ව මගින් ලබා දෙන
<T, eta, _*>
අන්තරාසර්ගයක
T : C -> C
( f
), අනන්යතා මෝෆිස්වාදය eta
( return
) සහ දිගු කිරීමේ ක්රියාකරු *
( =<<
).
සෑම ක්ලයිස්ලි මෝෆිස්මය Hask
f : X -> T(Y)
f :: a -> m b
දිගු කිරීමේ ක්රියාකරු විසින්
(_)* : Hom(X, T(Y)) -> Hom(T(X), T(Y))
(=<<) :: (a -> m b) -> (m a -> m b)
දී morphism ලබා දෙන Hask
ගේ Kleisli ප්රවර්ගය
f* : T(X) -> T(Y)
(f =<<) :: m a -> m b
ක්ලයිස්ලි කාණ්ඩයේ සංයුතිය දීර් .T
extension කිරීම අනුව ලබා දී ඇත
f .T g = f* . g : X -> T(Z)
f <=< g = (f =<<) . g :: a -> m c
සහ අක්ෂර අක්ෂර තෘප්තිමත් කරයි
eta .T g = g : Y -> T(Z) Left identity
return <=< g = g :: b -> m c
f .T eta = f : Z -> T(U) Right identity
f <=< return = f :: c -> m d
(f .T g) .T h = f .T (g .T h) : X -> T(U) Associativity
(f <=< g) <=< h = f <=< (g <=< h) :: a -> m d
සමානතා පරිවර්තනයන් යෙදීම
eta .T g = g
eta* . g = g By definition of .T
eta* . g = id . g forall f. id . f = f
eta* = id forall f g h. f . h = g . h ==> f = g
(f .T g) .T h = f .T (g .T h)
(f* . g)* . h = f* . (g* . h) By definition of .T
(f* . g)* . h = f* . g* . h . is associative
(f* . g)* = f* . g* forall f g h. f . h = g . h ==> f = g
දිගුව සම්බන්ධයෙන් කැනොනිකල් ලෙස ලබා දී ඇත
eta* = id : T(X) -> T(X) Left identity
(return =<<) = id :: m t -> m t
f* . eta = f : Z -> T(U) Right identity
(f =<<) . return = f :: c -> m d
(f* . g)* = f* . g* : T(X) -> T(Z) Associativity
(((f =<<) . g) =<<) = (f =<<) . (g =<<) :: m a -> m c
Monads ද Kleislian දීර්ඝ අනුව නොවේ අර්ථ හැක, නමුත් ස්වාභාවික පරිවර්තනය mu
, නමින් වැඩසටහන් තුළ join
. මොනාඩ් එකක් අර්ථ දැක්වෙන්නේ mu
එක් කාණ්ඩයකට වඩා ත්රිත්වයක් C
, එන්ඩොෆන්ක්ටර් ය
T : C -> C
f :: * -> *
සහ ස්වාභාවික සංවර්ධන දෙකක්
eta : Id -> T
return :: t -> f t
mu : T . T -> T
join :: f (f t) -> f t
සමානකම් තෘප්තිමත් කිරීම
mu . T(mu) = mu . mu : T . T . T -> T . T Associativity
join . map join = join . join :: f (f (f t)) -> f t
mu . T(eta) = mu . eta = id : T -> T Identity
join . map return = join . return = id :: f t -> f t
මොනාඩ් වර්ගයේ පන්තිය පසුව අර්ථ දැක්වේ
class Functor m => Monad m where
return :: t -> m t
join :: m (m t) -> m t
mu
මොනාඩ් විකල්පය කැනොනිකල් ක්රියාත්මක කිරීම:
instance Monad Maybe where
return = Just
join (Just m) = m
join Nothing = Nothing
මෙම concat
උත්සවය
concat :: [[a]] -> [a]
concat (x : xs) = x ++ concat xs
concat [] = []
යනු join
ලැයිස්තුව monad ය.
instance Monad [] where
return :: t -> [t]
return = (: [])
(=<<) :: (a -> [b]) -> ([a] -> [b])
(f =<<) = concat . map f
ක්රියාත්මක කිරීම join
සමානතා භාවිතා කරමින් ව්යාප්ති පෝරමයෙන් පරිවර්තනය කළ හැකිය
mu = id* : T . T -> T
join = (id =<<) :: m (m t) -> m t
ප්රතිලෝම පරිවර්තනය සිට mu
දිගු කිරීමේ ආකෘතිය දක්වා ඇත්තේ
f* = mu . T(f) : T(X) -> T(Y)
(f =<<) = join . map f :: m a -> m b
පිලිප් වැඩ්ලර්: ක්රියාකාරී වැඩසටහන් සඳහා මොනාඩ්ස්
සයිමන් එල් පීටන් ජෝන්ස්, පිලිප් වැඩ්ලර්: අත්යවශ්ය ක්රියාකාරී වැඩසටහන්කරණය
ජොනතන් කළමනාකාර අධ්යක්ෂ හිල්, කීත් ක්ලාක්: ශ්රිතීය ක්රමලේඛණය කිරීමට ප්රවර්ගය න්යාය, ප්රවර්ගය න්යාය monads, සහ ඔවුන්ගේ සම්බන්ධතාවය පිළිබඳ හැඳින්වීමක් '
ඉයුජීනියෝ මොග්ගි: ගණනය කිරීම් සහ මොනාඩ්ස් පිළිබඳ අදහස්
නමුත් වියුක්ත න්යායක් ක්රමලේඛනය සඳහා කිසියම් ප්රයෝජනයක් විය යුත්තේ ඇයි?
පිළිතුර සරල ය: පරිගණක විද්යා scientists යින් වශයෙන් අපි වියුක්ත කිරීම අගය කරමු ! අපි අතුරු මුහුණත මෘදුකාංග සංරචකයකට සැලසුම් කරන විට, එය ක්රියාත්මක කිරීම පිළිබඳව හැකි තරම් සුළු ප්රමාණයක් හෙළි කිරීමට අපට අවශ්යය . ක්රියාත්මක කිරීම බොහෝ විකල්පයන් සමඟ ප්රතිස්ථාපනය කිරීමට අපට අවශ්යය, එකම 'සංකල්පයේ' තවත් බොහෝ අවස්ථා. අපි බොහෝ වැඩසටහන් පුස්තකාල සඳහා සාමාන්ය අතුරු මුහුණතක් නිර්මාණය කරන විට, අප තෝරා ගන්නා අතුරු මුහුණතෙහි විවිධාකාර ක්රියාත්මක කිරීම් තිබීම ඊටත් වඩා වැදගත් ය. මොනාඩ් සංකල්පයේ සාමාන්ය භාවය අප බෙහෙවින් අගය කරන අතර, එයට හේතුව කාණ්ඩ න්යාය වියුක්ත බැවින් එහි සංකල්ප ක්රමලේඛනය සඳහා එතරම් ප්රයෝජනවත් වේ.
එසේ නම්, අප පහත ඉදිරිපත් කරන මොනාඩ් සාමාන්යකරණය කිරීම ද කාණ්ඩ න්යායට සමීප සම්බන්ධයක් ඇති බව කිසිසේත්ම අධිපති නොවේ. නමුත් අපගේ අරමුණ ඉතා ප්රායෝගික බව අපි අවධාරණය කරමු: එය 'වර්ගීකරණ න්යාය ක්රියාත්මක කිරීම' නොවේ, එය සංයුක්ත පුස්තකාල සැකසීමට වඩාත් පොදු ක්රමයක් සොයා ගැනීමයි. ගණිත ians යන් දැනටමත් අප වෙනුවෙන් බොහෝ කාර්යයන් කර තිබීම අපගේ වාසනාවකි!
ජෝන් හියුස් විසින් මොනාඩ්ස් සිට ඊතල දක්වා සාමාන්යකරණය කිරීම
මම නිවැරදිව තේරුම් ගෙන ඇත්නම්, IEnumerable ව්යුත්පන්න වී ඇත්තේ මොනාඩ් වලින්. C # ලෝකයෙන් අප එන අයට එය සිත්ගන්නාසුලු ප්රවේශ කෝණයක් විය හැකිදැයි මම කල්පනා කරමි.
එය වටින දෙය සඳහා, මෙන්න මට උදව් කළ නිබන්ධන සඳහා සබැඳි කිහිපයක් (සහ නැත, මොනාඩ්ස් යනු කුමක්දැයි මට තවමත් වැටහී නැත).
එහි ඉගෙනීමේදී මට වඩාත්ම උපකාරවත් වූ කරුණු දෙක නම්:
8 වන පරිච්ඡේදය, ග්රැහැම් හටන්ගේ හස්කල් හි ක්රමලේඛන පොතේ “ක්රියාකාරී පාර්සර්ස්” . ඇත්ත වශයෙන්ම මෙය මොනාඩ්ස් ගැන සඳහන් නොකරයි, නමුත් ඔබට පරිච්ඡේදය හරහා වැඩ කර එහි ඇති සියල්ල සැබවින්ම තේරුම් ගත හැකි නම්, විශේෂයෙන් බන්ධන මෙහෙයුම් අනුපිළිවෙලක් තක්සේරු කරන්නේ කෙසේද, ඔබට මොනාඩ් වල අභ්යන්තරය අවබෝධ වනු ඇත. මෙය උත්සාහයන් කිහිපයක් ගැනීමට බලාපොරොත්තු වන්න.
All About Monads පිළිබඳ නිබන්ධනය . මෙය ඒවායේ භාවිතය පිළිබඳ හොඳ උදාහරණ කිහිපයක් ලබා දෙන අතර, මට කියන්නට ඇත්තේ මා වෙනුවෙන් වැඩ කළ උපග්රන්ථයේ ඇති ප්රතිසමයන් ය.
මොනොයිඩ් සහ ආධාරක වර්ගයක් මත අර්ථ දක්වා ඇති සියලුම මෙහෙයුම් සෑම විටම මොනොයිඩ් තුළ ආධාරක වර්ගයක් නැවත ලබා දෙන බව සහතික කරන දෙයක් ලෙස මොනොයිඩ් පෙනේ. උදා, ඕනෑම අංකයක් + ඕනෑම අංකයක් = අංකයක්, දෝෂ නොමැත.
කොට් division ාශය භාග දෙකක් පිළිගන්නා අතර භාගයක් ආපසු ලබා දෙයි, එය ශුන්යයෙන් බෙදීම අර්ථ දක්වා ඇත්තේ හස්කල් හි අනන්තය ලෙසිනි (එය භාගික වශයෙන් කෙසේ හෝ වේ) ...
කෙසේ වෙතත්, මොනාඩ්ස් යනු ඔබේ මෙහෙයුම් දාමය පුරෝකථනය කළ හැකි ආකාරයෙන් හැසිරෙන බව සහතික කිරීම සඳහා වූ ක්රමයක් පමණක් වන අතර, අංක -> අංක ලෙස ප්රකාශ කරන ශ්රිතයක්, අංක-> අංක x හි තවත් ශ්රිතයක් සමඟ සංයුක්ත වේ. කියන්න, මිසයිල වලට වෙඩි තියන්න.
අනෙක් අතට, අපට මිසයිල වෙඩි තබන ශ්රිතයක් තිබේ නම්, අපට එය වෙනත් කාර්යයන් සමඟ සංයුක්ත කළ හැකිය, එය මිසයිල වලට වෙඩි තබයි, මන්ද අපගේ අභිප්රාය පැහැදිලිය - අපට මිසයිල වෙඩි තැබීමට අවශ්යය - නමුත් එය උත්සාහ නොකරනු ඇත කිසියම් අමුතු හේතුවක් නිසා "හෙලෝ වර්ල්ඩ්" මුද්රණය කිරීම.
හැස්කෙල් හි ප්රධාන වන්නේ IO () හෝ IO [()] වර්ගයේ ය, වෙනස අමුතු ය, මම එය සාකච්ඡා නොකරමි නමුත් මෙහි සිදුවන්නේ යැයි මා සිතන දේ ය:
මට ප්රධාන නම්, එය ක්රියා දාමයක් කිරීමට මට අවශ්යය, මම වැඩසටහන ක්රියාත්මක කිරීමට හේතුව බලපෑමක් ඇති කිරීමයි - සාමාන්යයෙන් අයි.ඕ. මේ අනුව මට ප්රධාන වශයෙන් IO මෙහෙයුම් එකට සම්බන්ධ කළ හැකිය - IO කරන්න, වෙන කිසිවක් නැත.
“IO ආපසු නොදෙන” යමක් කිරීමට මම උත්සාහ කළහොත්, දාමය ගලා නොයන බවට වැඩසටහන පැමිණිලි කරනු ඇත, නැතහොත් මූලික වශයෙන් “මෙය අප කිරීමට උත්සාහ කරන දෙයට සම්බන්ධ වන්නේ කෙසේද - IO ක්රියාවක්”, එය බල කරන බව පෙනේ ක්රමලේඛකයා මිසයිල වෙඩි තැබීම ගැන නොසිතා, කල්පනා නොකර තම සිතුවිලි දුම්රිය තබා ගැනීමටත්, වර්ග කිරීම සඳහා ඇල්ගොරිතම නිර්මාණය කිරීමටත් - ගලා නොයයි.
මූලික වශයෙන්, මොනාඩ්ස් සම්පාදකයාට ඉඟියක් ලෙස පෙනේ, "ඒයි, ඔබ මෙහි අංකයක් ලබා දෙන මෙම ශ්රිතය දන්නවා, එය සැබවින්ම සැමවිටම ක්රියා නොකරයි, එය සමහර විට අංකයක් නිපදවිය හැකිය, සමහර විට කිසිවක් නැත, මෙය තබා ගන්න මනස ". මෙය දැන ගැනීමෙන්, ඔබ මොනාඩික් ක්රියාවක් ප්රකාශ කිරීමට උත්සාහ කරන්නේ නම්, මොනාඩික් ක්රියාව සම්පාදිත කාල ව්යතිරේකයක් ලෙස ක්රියා කළ හැකිය, "ඒයි, මෙය ඇත්ත වශයෙන්ම අංකයක් නොවේ, මෙය අංකයක් විය හැකිය, නමුත් ඔබට මෙය උපකල්පනය කළ නොහැක, යමක් කරන්න ප්රවාහය පිළිගත හැකි බව සහතික කිරීම සඳහා. එය අනපේක්ෂිත වැඩසටහන් හැසිරීම වළක්වයි - සාධාරණ ප්රමාණයකට.
මොනාඩ්ස් යනු සංශුද්ධතාවය හෝ පාලනය ගැන නොව, සියලු හැසිරීම් පුරෝකථනය කළ හැකි සහ නිර්වචනය කර ඇති හෝ සම්පාදනය නොකරන කාණ්ඩයක අනන්යතාවයක් පවත්වා ගැනීම ගැන ය. ඔබ යමක් කිරීමට අපේක්ෂා කරන විට ඔබට කිසිවක් කළ නොහැකි අතර ඔබ කිසිවක් නොකරනු ඇතැයි අපේක්ෂා කරන්නේ නම් ඔබට යමක් කළ නොහැක (දෘශ්යමාන).
මොනාඩ්ස් සඳහා මට සිතිය හැකි ලොකුම හේතුව නම් - ක්රියා පටිපාටිය / ඕඕපී කේතය දෙස බලන්න, එවිට වැඩසටහන ආරම්භ වන්නේ කොතැනින්ද, අවසන් වන්නේද යන්න ඔබ නොදන්නා බව ඔබට පෙනෙනු ඇත, ඔබ දකින සියල්ල පැනීම සහ ගණිතය ගොඩක් , මැජික් සහ මිසයිල. ඔබට එය නඩත්තු කිරීමට නොහැකි වනු ඇති අතර, ඔබට හැකි නම්, එහි ඕනෑම කොටසක් තේරුම් ගැනීමට පෙර ඔබේ මනස මුළු වැඩසටහන වටා එතීමට සෑහෙන කාලයක් ගත කරනු ඇත, මන්ද මෙම සන්දර්භය තුළ මොඩියුලරිටි භාවය රඳා පවතින්නේ එකිනෙකට පරායත්ත වූ “කොටස්” මත ය. කේතයේ, කාර්යක්ෂමතාව / අන්තර් සම්බන්ධතා පොරොන්දුව සඳහා කේතය හැකි තරම් සම්බන්ධ වීමට ප්රශස්තිකරණය කර ඇත. මොනාඩ්ස් ඉතා කොන්ක්රීට් වන අතර නිර්වචනය අනුව මනාව නිර්වචනය කර ඇති අතර ක්රමලේඛයේ ප්රවාහය විශ්ලේෂණය කිරීමට හැකි බව සහතික කිරීමට සහ විශ්ලේෂණය කිරීමට අපහසු කොටස් හුදකලා කිරීමට - ඒවා මොනාඩ් බැවින්. මොනාඩ් එකක් " හෝ විශ්වය විනාශ කිරීම හෝ කාලය විකෘති කිරීම පවා - එය කුමක්දැයි අපට කිසිම අදහසක් හෝ සහතිකයක් නොමැත. එය කුමක්දැයි සහතික කරන මොනාඩ්. එය ඉතා බලවත් ය. හෝ විශ්වය විනාශ කිරීම හෝ කාලය විකෘති කිරීම පවා - එය කුමක්දැයි අපට කිසිම අදහසක් හෝ සහතිකයක් නොමැත. එය කුමක්දැයි සහතික කරන මොනාඩ්. එය ඉතා බලවත් ය.
"තාත්වික ලෝකයේ" සෑම දෙයක්ම මොනාඩ්ස් ලෙස පෙනේ, එය ව්යාකූලත්වය වළක්වන නිශ්චිත නිරීක්ෂණය කළ හැකි නීති මගින් බැඳී ඇත. පංති නිර්මාණය කිරීම සඳහා මෙම වස්තුවේ සියලු ක්රියාකාරකම් අනුකරණය කළ යුතු යැයි මින් අදහස් නොකෙරේ, ඒ වෙනුවට අපට සරලව කිව හැක්කේ “චතුරස්රයක් යනු චතුරස්රයක්”, චතුරස්රයක් හැර අන් කිසිවක්, සෘජුකෝණාස්රයක් හෝ රවුමක් හෝ "චතුරස්රයක් ප්රදේශයක් ඇත එහි පවත්නා මානයන්ගෙන් එකක දිග තමා විසින්ම ගුණ කරනු ලැබේ.ඔබට ඇති චතුරස්රය කුමක් වුවත්, එය 2D අවකාශයේ වර්ගයක් නම්, එහි ප්රදේශය නියත වශයෙන්ම කිසිවක් විය නොහැකිය, නමුත් එහි දිග කොටු වේ, එය ඔප්පු කිරීම ඉතා සුළුය. මෙය ඉතා බලවත් නිසා අපේ ලෝකය එලෙසම බව තහවුරු කර ගැනීම සඳහා අපට ප්රකාශ කිරීම අවශ්ය නොවේ, අපගේ වැඩසටහන් මඟ හැරී යාම වැළැක්වීම සඳහා අපි යථාර්ථයේ ඇඟවුම් භාවිතා කරමු.
මම වැරදියි කියා බොහෝ සෙයින් සහතික වී ඇති නමුත් මම සිතන්නේ මෙය පිටත සිටින කෙනෙකුට උදව් කළ හැකි නිසා එය යමෙකුට උපකාර කරයි.
Scala හි සන්දර්භය තුළ පහත සඳහන් දේ සරලම අර්ථ දැක්වීම ලෙස ඔබට පෙනෙනු ඇත. මූලික වශයෙන් පැතලි සිතියම (හෝ බන්ධනය) 'සහායක' වන අතර අනන්යතාවයක් පවතී.
trait M[+A] {
def flatMap[B](f: A => M[B]): M[B] // AKA bind
// Pseudo Meta Code
def isValidMonad: Boolean = {
// for every parameter the following holds
def isAssociativeOn[X, Y, Z](x: M[X], f: X => M[Y], g: Y => M[Z]): Boolean =
x.flatMap(f).flatMap(g) == x.flatMap(f(_).flatMap(g))
// for every parameter X and x, there exists an id
// such that the following holds
def isAnIdentity[X](x: M[X], id: X => M[X]): Boolean =
x.flatMap(id) == x
}
}
උදා
// These could be any functions
val f: Int => Option[String] = number => if (number == 7) Some("hello") else None
val g: String => Option[Double] = string => Some(3.14)
// Observe these are identical. Since Option is a Monad
// they will always be identical no matter what the functions are
scala> Some(7).flatMap(f).flatMap(g)
res211: Option[Double] = Some(3.14)
scala> Some(7).flatMap(f(_).flatMap(g))
res212: Option[Double] = Some(3.14)
// As Option is a Monad, there exists an identity:
val id: Int => Option[Int] = x => Some(x)
// Observe these are identical
scala> Some(7).flatMap(id)
res213: Option[Int] = Some(7)
scala> Some(7)
res214: Some[Int] = Some(7)
සටහන පිටුව අතිශයින්ම ඉතා අර්ථ දැක්වීම කතා ශ්රිතීය ක්රමලේඛණය තුල Monad වූ අර්ථ දැක්වීම සමාන නොවේ ප්රවර්ගය න්යාිය Monad ක සඹපූේණ අර්ථ ඇති, map
හා flatten
. සමහර සිතියම්කරණය යටතේ ඒවා සමාන වේ. මෙම ඉදිරිපත් කිරීම් ඉතා හොඳයි: http://www.slideshare.net/samthemonad/monad-presentation-scala-as-a-category
මෙම පිළිතුර ආරම්භ වන්නේ අභිප්රේරිත උදාහරණයකින් වන අතර, උදාහරණය හරහා ක්රියා කරයි, මොනාඩ් පිළිබඳ උදාහරණයක් ලබා ගනී, සහ විධිමත් ලෙස "මොනාඩ්" යන්න අර්ථ දක්වයි.
ව්යාජ කේතයේ මෙම කාර්යයන් තුන සලකා බලන්න:
f(<x, messages>) := <x, messages "called f. ">
g(<x, messages>) := <x, messages "called g. ">
wrap(x) := <x, "">
f
පෝරමයේ <x, messages>
ඇණවුම් යුගලයක් ගෙන ඇණවුම් කළ යුගලයක් ආපසු ලබා දේ. එය පළමු අයිතමය ස්පර්ශ "called f. "
නොකර දෙවන අයිතමයට එකතු කරයි. සමග එකම g
.
ඔබට මෙම ශ්රිත රචනා කර ඔබේ මුල් අගය ලබා ගත හැකිය.
f(g(wrap(x)))
= f(g(<x, "">))
= f(<x, "called g. ">)
= <x, "called g. called f. ">
ඔබ යන කාරනය අකමැති f
හා g
පෙර දැව සදහා තොරතුරු ඔවුන්ගේ ම ලඝු-සටහන පණිවුඩ appending සඳහා වගකිව යුතු වේ. (නූල් appending වෙනුවට එම තර්කය වෙනුවෙන් සිතා බලන්න, f
සහ g
මේ දෙදෙනා දෙවැනි අයිතමය මත තර්ක සංකීර්ණ එය සංකීර්ණ දෙකක් තර්කණයෙන් නැවත කිරීමට වේදනාව වනු ඉටු කළ යුතුයි -. හෝ ඊට වැඩි -. විවිධ කටයුතු)
සරල කාර්යයන් ලිවීමට ඔබ කැමති:
f(x) := <x, "called f. ">
g(x) := <x, "called g. ">
wrap(x) := <x, "">
නමුත් ඔබ ඒවා රචනා කළ විට කුමක් සිදුවේදැයි බලන්න:
f(g(wrap(x)))
= f(g(<x, "">))
= f(<<x, "">, "called g. ">)
= <<<x, "">, "called g. ">, "called f. ">
ගැටළුව වන්නේ ශ්රිතයක් තුළට යුගලයක් යැවීම ඔබට අවශ්ය දේ ලබා නොදීමයි. නමුත් ඔබට පෝෂණය කළ හැකි නම් ශ්රිතයක් සඳහා යුගලයක් :
feed(f, feed(g, wrap(x)))
= feed(f, feed(g, <x, "">))
= feed(f, <x, "called g. ">)
= <x, "called g. called f. ">
කියවන්න feed(f, m)
"ආහාර ලෙස m
බවට f
". කිරීමට පෝෂණය යුගලයක් <x, messages>
උත්සවයකට බවට f
ය සමත් x
බවට f
, ලබා <y, message>
පිටතට f
, සහ ඒ<y, messages message>
.
feed(f, <x, messages>) := let <y, message> = f(x)
in <y, messages message>
ඔබගේ කාර්යයන් සමඟ ඔබ කරුණු තුනක් කළ විට කුමක් සිදුවේදැයි බලන්න:
පළමුව: ඔබ අගයක් ඔතා ඉන්පසු ලැබෙන යුගලය ශ්රිතයකට පෝෂණය කරන්නේ නම්:
feed(f, wrap(x))
= feed(f, <x, "">)
= let <y, message> = f(x)
in <y, "" message>
= let <y, message> = <x, "called f. ">
in <y, "" message>
= <x, "" "called f. ">
= <x, "called f. ">
= f(x)
ඒ හා සමාන වේ , සමත් ශ්රිතයට අගය වේ.
දෙවනුව: ඔබ යුගලයක් පෝෂණය කරන්නේ නම් wrap
:
feed(wrap, <x, messages>)
= let <y, message> = wrap(x)
in <y, messages message>
= let <y, message> = <x, "">
in <y, messages message>
= <x, messages "">
= <x, messages>
එය යුගලය වෙනස් නොකරයි.
තෙවන: ඔබ යම් කිසි ශ්රිතයක් අර්ථ දැක්විය නම් x
සහ ආහාරයේ g(x)
බවට f
:
h(x) := feed(f, g(x))
එයට යුගලයක් පෝෂණය කරන්න:
feed(h, <x, messages>)
= let <y, message> = h(x)
in <y, messages message>
= let <y, message> = feed(f, g(x))
in <y, messages message>
= let <y, message> = feed(f, <x, "called g. ">)
in <y, messages message>
= let <y, message> = let <z, msg> = f(x)
in <z, "called g. " msg>
in <y, messages message>
= let <y, message> = let <z, msg> = <x, "called f. ">
in <z, "called g. " msg>
in <y, messages message>
= let <y, message> = <x, "called g. " "called f. ">
in <y, messages message>
= <x, messages "called g. " "called f. ">
= feed(f, <x, messages "called g. ">)
= feed(f, feed(g, <x, messages>))
එය යුගලයට g
පෝෂණය කිරීම හා එහි ප්රති pair ලයක් ලෙස යුගලය පෝෂණය කිරීම හා සමාන f
වේ.
ඔබට බොහෝ මොනාඩ් ඇත. දැන් ඔබ ඔබේ වැඩසටහනේ දත්ත වර්ග ගැන දැනගත යුතුය.
කුමන වර්ගයේ වටිනාකමක් ද <x, "called f. ">
? හොඳයි, එය රඳා පවතින්නේ කුමන ආකාරයේ වටිනාකමක්ද x
යන්න මතය. නම් x
ආකාරයේ වන t
, එසේ නම් ඔබේ යුගල වර්ගය "යුගල අතර එහි වටිනාකම වන t
සහ string". එම වර්ගයට අමතන්න M t
.
M
වර්ගය සාදන්නෙක්: M
තනිවම වර්ගයක් ගැන සඳහන් නොකරයි, නමුත් M _
ඔබ වර්ගයක් සමඟ හිස්ව පුරවා ගත් පසු වර්ගයක් අදහස් කරයි. An M int
යනු int සහ නූල් යුගලයකි. An M string
යනු නූල් යුගලයක් සහ නූලකි. ආදිය.
සුභ පැතුම්, ඔබ මොනාඩ් එකක් නිර්මාණය කර ඇත!
විධිමත් ලෙස, ඔබේ මොනාඩ් යනු ටුපල් ය <M, feed, wrap>
.
මොනාඩ් යනු ටුපල් <M, feed, wrap>
ය:
M
වර්ගයේ ඉදිකිරීම්කරුවෙකි.feed
එය (අ ගත වන බව උත්සවය ගනී t
හා නැවත M u
) හා M t
හා නැවත පැමිණීම M u
.wrap
a v
ගෙන ආපසු එයි M v
.t
,, u
සහ v
සමාන විය හැකි හෝ නොවිය හැකි ඕනෑම වර්ග තුනක් වේ. ඔබේ විශේෂිත මොනාඩ් සඳහා ඔබ ඔප්පු කළ ගුණාංග තුන මොනාඩ් විසින් තෘප්තිමත් කරයි:
t
ශ්රිතයකට ඔතා පෝෂණය කිරීම ශ්රිතයට නොකැඩූ ලෙස ගමන් කිරීම හා සමාන t
වේ.
විධිමත් ලෙස: feed(f, wrap(x)) = f(x)
ක ආහාර M t
බවට wrap
ද කිරීමට කිසිවක් කර නැත M t
.
විධිමත් ලෙස: feed(wrap, m) = m
M t
(එය අමතන්න m
) එම ශ්රිතයට පෝෂණය කිරීම
t
බවටg
M u
(එය අමතන්න n
) සිටg
n
තුළට පෝෂණය වේf
සමාන වේ
m
කිරීමg
n
සිට ලබා ගැනීමg
n
කිරීමf
විධිමත් ලෙස: feed(h, m) = feed(f, feed(g, m))
කොහෙදh(x) := feed(f, g(x))
සාමාන්යයෙන්, feed
ලෙස හැඳින්වේ bind
(aka >>=
Haskell දී) සහ wrap
හැඳින්වේ return
.
මම Monad
හස්කල්ගේ සන්දර්භය තුළ පැහැදිලි කිරීමට උත්සාහ කරමි .
ක්රියාකාරී වැඩසටහන්කරණයේදී, ක්රියාකාරී සංයුතිය වැදගත් වේ. එය අපගේ වැඩසටහනට කුඩා, පහසුවෙන් කියවිය හැකි කාර්යයන් වලින් සමන්විත වේ.
අපට කාර්යයන් දෙකක් ඇති බව කියමු: g :: Int -> String
සහ f :: String -> Bool
.
අපට කළ හැකිය (f . g) x
, එය වටිනාකමක් ඇති f (g x)
තැනට සමාන x
වේ Int
.
සංයුතිය සිදු කරන විට / එක් ශ්රිතයක ප්රති result ලය තවත් ක්රියාවකට යොදන විට, වර්ග ගැලපීම වැදගත් වේ. ඉහත අවස්ථාවෙහිදී, ලබා දුන් ප්රති result ල g
වර්ගය පිළිගත් වර්ගයට සමාන විය යුතුයf
.
නමුත් සමහර විට අගයන් සන්දර්භය තුළ පවතින අතර, මෙය වර්ග පෙළගැස්වීම ටිකක් අඩු කරයි. (සන්දර්භයන් තුළ සාරධර්ම තිබීම ඉතා ප්රයෝජනවත් වේ. උදාහරණයක් ලෙස, Maybe Int
වර්ගය නියෝජනය Int
කළ හැකි නො එම අගය, මේ IO String
වර්ගයේ නියෝජනය String
සමහර අතුරු ආබාධ සිදු කිරීමේ ප්රතිඵලයක් ලෙස ඇති බව අගය.)
දැන් අපි බලමු අපි දැන් කියන්න මට ඉඩ දෙන්න g1 :: Int -> Maybe String
සහ f1 :: String -> Maybe Bool
. g1
හා f1
ඉතා සමාන වේ g
හා f
පිළිවෙළින්.
අපි කරන්න බැහැ (f1 . g1) x
හෝ f1 (g1 x)
, කොහෙද x
යනු Int
අගය. ලබා දුන් ප්රති result ල වර්ගය අපේක්ෂා කරන g1
දේ නොවේ f1
.
අපි රචනා කළ හැකි f
හා g
සමග .
ක්රියාකරු, නමුත් දැන් අපි රචනා කළ නොහැකි f1
සහ g1
සමග .
. ගැටළුව වන්නේ සන්දර්භය තුළ නැති අගයක් අපේක්ෂා කරන ශ්රිතයකට සන්දර්භය තුළ අපට වටිනාකමක් කෙලින්ම ලබා දිය නොහැකි වීමයි.
අපි රචනා කිරීමට ක්රියාකරුවෙකු හඳුන්වා දුන්නොත් g1
සහ f1
අපට ලිවිය හැකි තරම් හොඳ (f1 OPERATOR g1) x
නොවේද? g1
සන්දර්භයක් තුළ අගයක් ලබා දෙයි. වටිනාකම සන්දර්භයෙන් ඉවතට ගෙන අදාළ වේ f1
. ඔව්, අපට එවැනි ක්රියාකරුවෙකු සිටී. ඒ <=<
.
>>=
තරමක් වෙනස් වාක්ය ඛණ්ඩයක වුවද අපට හරියටම එකම දේ කරන ක්රියාකරු අප සතුව ඇත .
අපි ලියන්නේ : g1 x >>= f1
. g1 x
යනු Maybe Int
අගය. මෙම >>=
ක්රියාකරු බව ගැනීමට උපකාරී වේ Int
සන්දර්භය "සමහර විට නොව-එහි" පිටතට අගය, එය අදාළ f1
. ප්රති f1
a Maybe Bool
ලය, එනම්, සමස්ත >>=
මෙහෙයුමේ ප්රති result ලය වනු ඇත .
අවසාන වශයෙන්, Monad
ප්රයෝජනවත් වන්නේ ඇයි ? මක්නිසාද යත් Monad
, >>=
ක්රියාකරු නිර්වචනය කරන Eq
වර්ගයේ පන්තිය වන අතර ==
, /=
ක්රියාකරුවන් සහ ක්රියාකරුවන් අර්ථ දක්වන වර්ග පන්තියට සමාන වේ.
නිගමනය කිරීම සඳහා, Monad
වර්ගීකරණ පන්තිය මඟින් >>=
සන්දර්භය තුළ අගයන් ලබා දීමට අපට ඉඩ සලසන ක්රියාකරු නිර්වචනය කරයි (අපි මෙම මොනාඩික් අගයන් ලෙස හඳුන්වන්නේ) සන්දර්භයක් තුළ අගයන් අපේක්ෂා නොකරන කාර්යයන් සඳහා ය. සන්දර්භය ගැන සැලකිලිමත් වනු ඇත.
මෙහි මතක තබා ගත යුතු එක් දෙයක් තිබේ නම්, එය Monad
සන්දර්භය තුළ අගයන් ඇතුළත් වන ක්රියාකාරී සංයුතියට ඉඩ දෙයි .
ලෝකයට අවශ්ය වන්නේ තවත් මොනාඩ් බ්ලොග් සටහනකි, නමුත් වනාන්තරයේ පවතින මොනාඩ් හඳුනා ගැනීමට මෙය ප්රයෝජනවත් යැයි මම සිතමි.
ඉහත දැක්වෙන්නේ සියර්පින්ස්කි ත්රිකෝණය නම් වූ අස්ථියකි, මට ඇඳීමට මතක ඇති එකම අස්ථිය. ෆ්රැක්ටල්ස් යනු ඉහත ත්රිකෝණය මෙන් ස්වයං-සමාන ව්යුහයකි, එහි කොටස් සමස්තයට සමාන වේ (මේ අවස්ථාවේ දී මව් ත්රිකෝණය මෙන් හරියටම පරිමාණයෙන් අඩක්).
මොනාඩ්ස් යනු අස්ථි බිඳීම් ය. මොනාඩික් දත්ත ව්යුහයක් ලබා දී ඇති විට, දත්ත ව්යුහයේ තවත් අගයක් සැකසීම සඳහා එහි අගයන් රචනා කළ හැකිය. මෙය වැඩසටහන්කරණයට ප්රයෝජනවත් වන්නේ එබැවිනි, බොහෝ අවස්ථාවන්හිදී එය සිදුවන්නේ මේ නිසාය.
http://code.google.com/p/monad-tutorial/ යනු මෙම ප්රශ්නයට හරියටම විසඳුම් සෙවීමේ ක්රියාවලියකි.
පහත දැක්වෙන " {| a |m}
" සමහර මොනාඩික් දත්ත නියෝජනය කිරීමට ඉඩ දෙන්න . ප්රචාරණය කරන දත්ත වර්ගයක් a
:
(I got an a!)
/
{| a |m}
ශ්රිතය, f
මොනාඩ් එකක් නිර්මාණය කරන්නේ කෙසේදැයි දනී, එයට එය තිබුනේ නම් පමණි a
:
(Hi f! What should I be?)
/
(You?. Oh, you'll be /
that data there.) /
/ / (I got a b.)
| -------------- |
| / |
f a |
|--later-> {| b |m}
මෙහිදී අපට ක්රියාකාරිත්වය පෙනේ, f
මොනාඩ් එකක් තක්සේරු කිරීමට උත්සාහ කළද තරවටු කරනු ලැබේ.
(Hmm, how do I get that a?)
o (Get lost buddy.
o Wrong type.)
o /
f {| a |m}
Funtion, භාවිතා කිරීමෙන් f
උපුටා ගැනීම සඳහා ක්රමයක් සොයා ගනී .a
>>=
(Muaahaha. How you
like me now!?)
(Better.) \
| (Give me that a.)
(Fine, well ok.) |
\ |
{| a |m} >>= f
f
මොනාඩ් සහ එකට එකතු >>=
වී ඇති බව දන්නේ නැත .
(Yah got an a for me?)
(Yeah, but hey |
listen. I got |
something to |
tell you first |
...) \ /
| /
{| a |m} >>= f
නමුත් ඔවුන් ඇත්තටම කතා කරන්නේ කුමක් ගැනද? හොඳයි, එය මොනාඩ් මත රඳා පවතී. වියුක්තව පමණක් කථා කිරීම සීමිත භාවිතයක් ඇත; අවබෝධය ලබා ගැනීම සඳහා ඔබට විශේෂිත මොනාඩ්ස් සමඟ යම් අත්දැකීමක් තිබිය යුතුය.
උදාහරණයක් ලෙස, දත්ත වර්ගය සමහර විට
data Maybe a = Nothing | Just a
පහත දැක්වෙන ආකාරයට ක්රියා කරන මොනාඩ් උදාහරණයක් ඇත ...
නඩුව නම් Just a
(Yah what is it?)
(... hm? Oh, |
forget about it. |
Hey a, yr up.) |
\ |
(Evaluation \ |
time already? \ |
Hows my hair?) | |
| / |
| (It's |
| fine.) /
| / /
{| a |m} >>= f
නමුත් නඩුව සඳහා Nothing
(Yah what is it?)
(... There |
is no a. ) |
| (No a?)
(No a.) |
| (Ok, I'll deal
| with this.)
\ |
\ (Hey f, get lost.)
\ | ( Where's my a?
\ | I evaluate a)
\ (Not any more |
\ you don't. |
| We're returning
| Nothing.) /
| | /
| | /
| | /
{| a |m} >>= f (I got a b.)
| (This is \
| such a \
| sham.) o o \
| o|
|--later-> {| b |m}
එබැවින් සමහර විට මොනාඩ් විසින් ගණනය කිරීමක් සත්ය වශයෙන්ම එහි a
දැන්වීම් පළ කර තිබේ නම් එය දිගටම කරගෙන යාමට ඉඩ දෙයි , නමුත් එය එසේ නොවේ නම් ගණනය කිරීම නවතා දමයි. කෙසේ වෙතත්, ප්රති result ලය තවමත් ප්රති mon ලයක් නොව මොනාඩික් දත්ත කැබැල්ලකි f
. මෙම හේතුව නිසා, සමහර විට මොනාඩ් භාවිතා වන්නේ අසාර්ථකත්වයේ සන්දර්භය නිරූපණය කිරීමට ය.
විවිධ මොනාඩ්ස් වෙනස් ලෙස හැසිරේ. ලැයිස්තු යනු මොනාඩික් අවස්ථා සහිත වෙනත් දත්ත වර්ග වේ. ඔවුන් හැසිරෙන්නේ පහත සඳහන් ආකාරයට ය:
(Ok, here's your a. Well, its
a bunch of them, actually.)
|
| (Thanks, no problem. Ok
| f, here you go, an a.)
| |
| | (Thank's. See
| | you later.)
| (Whoa. Hold up f, |
| I got another |
| a for you.) |
| | (What? No, sorry.
| | Can't do it. I
| | have my hands full
| | with all these "b"
| | I just made.)
| (I'll hold those, |
| you take this, and /
| come back for more /
| when you're done /
| and we'll do it /
| again.) /
\ | ( Uhhh. All right.)
\ | /
\ \ /
{| a |m} >>= f
මෙම අවස්ථාවෙහිදී, ශ්රිතය එහි ආදානයෙන් ලැයිස්තුවක් සාදා ගන්නේ කෙසේදැයි දැන සිටියද අතිරේක ආදානය සහ අමතර ලැයිස්තු සමඟ කුමක් කළ යුතු දැයි නොදැන සිටියේය. බන්ධනය >>=
, f
බහු ප්රතිදානයන් ඒකාබද්ධ කිරීමෙන් උපකාරී වේ. >>=
නිස්සාරණය සඳහා වගකිව යුතු අතර a
, අවසානයේදී බැඳී ඇති නිමැවුමට ප්රවේශය ද ඇති බව පෙන්වීමට මම මෙම උදාහරණය ඇතුළත් කරමි f
. ඇත්ත වශයෙන්ම, a
අවසාන නිමැවුමට එකම ආකාරයේ සන්දර්භයක් ඇති බව නොදැන එය කිසි විටෙකත් උපුටා නොගනී.
විවිධ සන්දර්භයන් නිරූපණය කිරීම සඳහා භාවිතා කරන වෙනත් මොනාඩ් තිබේ. මෙන්න තවත් කිහිපයක ලක්ෂණ කිහිපයක්. මෙම IO
monad ඇත්තටම කිරීමක් නොමැති a
, නමුත්, එය මෙයා දන්නවා ඒ ලැබෙනු ඇත a
. ඔබට මෙම State st
monad රහසිගත මැට්ටෙක් ඇත st
එය සමත් වනු ඇත බව f
, මේසය යට වුවත් f
හුදෙක් ඉල්ලා පැමිණි a
. මෙම Reader r
monad සමාන වේ State st
එය පමණක් ඉඩ දෙනවා වුවත්, f
සලකා බලන r
.
මේ සියල්ලෙහිම කාරණය නම්, මොනාඩ් ලෙස ප්රකාශයට පත් කරන ඕනෑම දත්ත වර්ගයක් මොනාඩ් වෙතින් වටිනාකමක් උකහා ගැනීම වටා යම් ආකාරයක සන්දර්භයක් ප්රකාශ කිරීමයි. මේ සියල්ලෙන් විශාල වාසියක්? හොඳයි, යම් ආකාරයක සන්දර්භයක් සමඟ ගණනය කිරීමක් කිරීමට එය පහසුය. කෙසේ වෙතත්, සන්දර්භය පටවා ඇති ගණනය කිරීම් එකට එකතු කිරීමේදී එය අවුල් විය හැක. ක්රමලේඛකයාට අවශ්ය නොවන පරිදි මොනාඩ් මෙහෙයුම් සන්දර්භයේ අන්තර්ක්රියා නිරාකරණය කිරීමට සැලකිලිමත් වේ.
සටහන, එම භාවිතය >>=
යම් ස්වයං පාලනයක් ඉවතට ගැනීමෙන් අවුල් ජාලයක් සමනය කරයි f
. එනම්, ඉහත Nothing
උදාහරණයේ දී, f
කුමක් කළ යුතු දැයි තීරණය කිරීමට තවදුරටත් නොලැබේ Nothing
; එය කේතනය කර ඇත >>=
. මෙය වෙළඳාමයි. f
නඩුවේදී කුමක් කළ යුතුද යන්න තීරණය කිරීම අවශ්ය වූයේ නම් Nothing
, එතැන් සිට එය f
කළ යුතු කාර්යයක් විය Maybe a
යුතුය Maybe b
. මෙම අවස්ථාවේ දී, Maybe
මොනාඩ් වීම අදාළ නොවේ.
කෙසේ වෙතත්, සමහර විට දත්ත වර්ගයක් එහි ඉදිකිරීම්කරුවන් අපනයනය නොකරන බව සලකන්න (ඔබ දෙස IO දෙස බලමින්), අපට ප්රචාරණය කළ අගය සමඟ වැඩ කිරීමට අවශ්ය නම් අපට එතරම් තේරීමක් නැති නමුත් එහි මොනාඩික් අතුරුමුහුණත සමඟ වැඩ කිරීම.
මොනාඩ් යනු වෙනස්වන තත්වයක් ඇති වස්තූන් සංයුක්ත කිරීම සඳහා භාවිතා කරන දෙයකි. බොහෝ විට ඔබට වෙනස් කළ හැකි තත්වයක් ඇති කිරීමට ඉඩ නොදෙන භාෂාවලින් (උදා: හස්කල්) හමු වේ.
I / O ගොනුව සඳහා උදාහරණයක් වනු ඇත.
වෙනස් වන රාජ්ය ස්වභාවය මොනාඩ් භාවිතා කළ කේතයට හුදකලා කිරීමට ඔබට I / O ගොනුව සඳහා මොනාඩ් භාවිතා කළ හැකිය. මොනාඩ් තුළ ඇති කේතයට මොනාඩ් වලින් පිටත ලෝකයේ වෙනස්වන තත්වය effectively ලදායී ලෙස නොසලකා හැරිය හැකිය - මෙය ඔබගේ වැඩසටහනේ සමස්ත බලපෑම ගැන තර්ක කිරීම පහසු කරයි.