Haskell
Haskell ստանդարտացված, ընդհանուր նշանակության մաքուր ֆունկցիոնալ ծրագրավորման լեզու: Տիպի համակարգը ամբողջական է, ստատիկ, ավտոմատ տիպի որոշմամբ, հիմնված Հինդլի-Միլներ տիպի համակարգի վրա: Քանի որ լեզուն ֆունկցիոնալ է, կառավարման հիմնական կառուցվածքը ֆունկցիան է: Լեզվի տարբերակիչ առանձնահատկությունն այն է, որ նա լուրջ վերաբերմունք ունի տիպավորման նկատմամբ։ Հիմնականում դրա շնորհիվ է, որ լեզուն անվանվել է տիպի տեսաբան և կոմբինատորային տրամաբանության գյուտարար Հասքել Քարիի անունով: Այս լեզուն ունի հնարավորություն ծրագրավորման այլ լեզուների կոդի հետ փոխազդելու միջոցներ։ Ներկառուցված է բազմաֆունկցիոնալ և զուգահեռ ծրագրավորման աջակցություն, մշակված գործիքներ (ավտոմատ թեստավորում, վրիպազերծման և պրոֆիլավորման գործիքներ, այդ թվում՝ զուգահեռ ծրագրերի համար), կան մի քանի հազար բաց կոդով գրադարաններ: ՊատմությունHaskell-ը պատկանում է ML լեզուների ընտանիքին։ Նրա վրա ուղղակիորեն ազդել է Միրանդա լեզուն, որը մշակվել է 1985 թվականին Դեյվիդ Թերները: Միրանդան առաջին մաքուր ֆունկցիոնալ լեզուն էր, որն ուներ կոմերցիոն աջակցություն և համեմատաբար տարածված էր 1980-ականներին, բայց մնաց սեփական ծրագրային ապահովման վրա: Սա դժվարացրեց զարգացնել և ուսումնասիրել ֆունկցիոնալ ծրագրավորման հնարավորությունները, ուստի ընդամենը մի քանի տարվա ընթացքում հայտնվեցին ավելի քան մեկ տասնյակ նմանատիպ լեզուներ: Տարբեր մշակողների ջանքերը միավորելու համար 1987 թվականին Օրեգոնի ֆունկցիոնալ ծրագրավորման լեզուների և համակարգչային ճարտարապետության կոնֆերանսում (FPCA'87), որոշվեց ստեղծել հանձնաժողով՝ բաց ստանդարտով մշակելու համար: 1990 թվականին առաջարկվեց լեզվի առաջին տարբերակը՝ Haskell 1.0։ Հետագայում հանձնաժողովի աշխատանքները շարունակվեցին, և 1999 թվականին լույս տեսավ «Haskell 98 զեկույցը»[6], որը երկար տարիներ դարձավ լեզվի կայուն չափանիշ։ Լեզուն, այնուամենայնիվ, շարունակեց արագ զարգանալ, քանի որ GHC կոմպիլյատորը դե ֆակտո ստանդարտ էր նոր հնարավորությունների համար: Լեզվի նոր տարբերակների մշակումը բաց է, այս գործընթացը կոչվում է Haskell'[7] (Haskell Prime [ˈhæskəl praɪm])։ Յուրաքանչյուր ոք կարող է իր առաջարկները ներկայացնել քննարկման, առաջարկները քննարկվում են ամբողջ տարվա ընթացքում, հանձնաժողովն ընտրում և հայտարարում է այն առաջարկները, որոնք պատրաստ են ընդունելու, ձևավորվում է նոր հանձնաժողով և մինչև տարեվերջ պատրաստվում է լեզվի նոր տարբերակը։ Այսպիսով, լեզվի նոր տարբերակներ այժմ կարող են հայտնվել ամեն տարի: Ծրագրով նախատեսվում է որոշ վերանայումներ հայտարարել «կարևոր» և պահպանել նման վերանայումները երկարատև ժամանակի ընթացքում: Haskell 2010 լեզվի տարբերակը հայտարարվել է 2009 թվականի վերջին[8], սակայն վերջին «նշանակալի» տարբերակը (ստանդարտ) մնում է Haskell 98-ը։ Լեզվի առանձնահատկություններըHaskell լեզվի հիմնական բնութագրերը հետևյալն են
Վերջին լեզվական ստանդարտի (Haskell'98) ընդունումից ի վեր, առաջատար լեզվական իրականացումները (ghc և hugs) լրացվել են բազմաթիվ լրացուցիչ հնարավորություններով։
Լեզվի իրականացումըHaskell լեզվի մի քանի իրականացում կա[10]: Որոշ իրականացումներ կենտրոնացած են գործնական կիրառությունների վրա, մինչդեռ մյուսները հիմնականում ակադեմիական հետաքրքրություն են ներկայացնում: Կոմպիլյատորներ և ինտերպրետատորներԳործնականում ամենատարածվածը[11] օպտիմիզացնող GHC կոմպիլյատորն է, որը ստեղծում է արագ կոդ և թույլ է տալիս օգտագործել բազմաթիվ լեզուների ընդլայնումներ։ GHC-ն կարող է օպտիմիզացնել ծրագրերի և՛ արագությունը, և՛ կոմպակտությունը, ինչպես նաև կարող է ստեղծել բազմաֆունկցիոնալ և զուգահեռացված կոդ: GHC-ն աշխատում է Windows, MacOS X և Unix-ի նման մի քանի հարթակներում (Linux, *BSD, Solaris): GHC-ն Haskell պլատֆորմի ստանդարտ կոմպիլյատորն է, և դրա վրա է, որ առաջին անգամ փորձարկվում են բոլոր նոր գրադարանները[12]: Լեզվի մեկ այլ հայտնի իրականացում HUGS թարգմանիչն է: Այն գրված է C- ով, ունի փոքր բաշխման չափ և աշխատում է գրեթե բոլոր հարթակներում։ HUGS-ն ապահովում է ինտերակտիվ ծրագրավորման միջավայր, բայց կարող է նաև գործարկել Haskell ծրագրերը սկրիպտային լեզուների ոճով: Windows-ի օգտվողները կարող են օգտվել WinHugs գրաֆիկական ինտերակտիվ միջավայրից: Քանի որ HUGS-ը թարգմանիչ է, դրանում աշխատող ծրագրերն ավելի դանդաղ են աշխատում, քան Haskell կոմպիլյատորների մեծամասնության կողմից արտադրված կոդը: HUGS-ը հաճախ առաջարկվում է որպես լեզվի ուսուցման միջավայր: HUGS-ը լիովին աջակցում է Haskell 98 լեզվի ստանդարտը, ինչպես նաև լեզվի ամենատարածված ընդլայնումներից մի քանիսը: Այլ հայտնի իրականացումներ[13]
Haskell Platform2009 թվականին ձևավորվեց Haskell պլատֆորմի[14] հայեցակարգը՝ լեզվի ստանդարտ բաշխում, որը ներառում է, բացի կոմպիլյատորից (GHC), նաև լրացուցիչ գործիքներ (Cabal փաթեթի կառուցման և տեղակայման համակարգ) և մի շարք հանրաճանաչ գրադարաններ։ 2022 թվականի դրությամբ Haskell Platform-ը համարվում է Haskell-ը տեղադրելու հնացած միջոց: Այլընտրանքային թիրախային հարթակներHaskell կոմպիլյատորների մեծամասնությունը ուղղակիորեն արտադրում է մեքենայական կոդ այն պլատֆորմի համար, որն օգտագործում եք, բայց կան մի քանի նախագծեր, որոնք թույլ են տալիս կոդ արտադրել վիրտուալ մեքենաների համար կամ ստեղծել կոդ այլ ծրագրավորման լեզուներով: Նման նախագծերի հասունությունը և աջակցության մակարդակը տարբերվում են:
YHC կոմպիլյատորի միջոցով հասանելի են մի քանի հետաքրքիր թիրախային հարթակներ, մասնավորապես՝ Python-ում YHC բայթկոդի թարգմանիչը և YHC բայթկոդը Erlang Core փոխարկիչում, բայց դրանք դեռ փորձնական են: Կան նաև լեզվի ենթաբազմությունների ներդրում տարբեր թիրախային հարթակներում։ Լեզուների ընդլայնումներ
Լեզվի իրականացման ընդլայնումներ(կիրառվում է GHC-ի համար).
ՕրինակներՖակտորիալի հաշվարկՀետևյալ օրինակը ցույց է տալիս Haskell-ի միջոցով ֆակտորիալը հաշվարկելու ֆունկցիան։ fac :: Integer -> Integer
fac 0 = 1
fac n | n > 0 = n * fac (n - 1)
Այս սահմանումը նկարագրում է ֆակտորիալ հաշվարկման գործընթացը որպես ռեկուրսիվ ֆունկցիա : Այս սահմանումը նման է համակարգչային գիտության դասագրքերում առկա սահմանմանը։ Վերը նշված օրինակը կարող է վերաշարադրվել հետևյալ ձևով fac n = product [1..n]
որը համապատասխանում է ֆակտորիայի մաթեմատիկական սահմանմանը։ Վերոնշյալ կոդի առաջին տողը պարտադիր չէ և որը համարվում է ֆունկցիոնալ տիպի հայտարարում, այսինքն՝ սահմանում է արգումենտի տեսակները (նշված վերջին « Երկրորդ և երրորդ տողերը կազմում են ֆունկցիայի մարմնի սահմանումը: Սահմանումը բաղկացած է նախադասություններից: Յուրաքանչյուր նախադասություն նմուշ-արտահայտություն զույգ է: Կոմպիլյատորը կամ թարգմանիչը օգտագործում է նմուշների համապատասխանության մեխանիզմ՝ արտահայտություններից մեկն ընտրելու համար: Այս դեպքում սահմանման երկրորդ տողը կընտրվի, երբ Երրորդ տողում, ի լրումն նմուծների համապատասխանության մեխանիզմի, օգտագործվում է լրացուցիչ արտահայտություն՝ ՀաշվիչՀակադարձ լեհական նշումով արտահայտությունները հաշվարկելու ամենապարզ հաշվիչը կարելի է սահմանել Haskell-ում՝ օգտագործելով մեկ ֆունկցիա calc :: String -> Float
calc = head . foldl f [] . words
where
f :: [Float] -> String -> [Float]
f (x:y:zs) "+" = (y + x):zs
f (x:y:zs) "-" = (y - x):zs
f (x:y:zs) "*" = (y * x):zs
f (x:y:zs) "/" = (y / x):zs
f (x:y:zs) "FLIP" = y:x:zs
f (x:zs) "ABS" = (abs x):zs
f xs y = read y : xs
Մուտքային արտահայտությամբ սկզբնական տողը այնուհետև բաժանվում է Այստեղ *Main> calc "1 2 3 + 4 * - ABS"
19.0
Ֆիբոնաչիի թվերՄեկ այլ օրինակ ցույց է տալիս Ֆիբոնաչիի թվերի անվերջ ցուցակը գծային ժամանակում հաշվարկելու եղանակ fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
Այստեղ անսահման ցուցակի հետագա արժեքները նշված են նախորդների հիման վրա՝ սկզբնական Այս սահմանումը ծույլ գնահատման մեխանիզմի օրինակ է, որը Haskell լեզվի կարևոր մասն է: Հասկանալու համար, թե ինչպես է գործում այս սահմանումը, կարող եք հաշվի առնել առաջին յոթ Ֆիբոնաչիի թվերը՝ օգտագործելով այն. fibs = 0 : 1 : 1 : 2 : 3 : 5 : 8 : ... + + + + + + tail fibs = 1 : 1 : 2 : 3 : 5 : 8 : ... = = = = = = zipWith (+) = 1 : 2 : 3 : 5 : 8 : ... fibs = 0 : 1 : 1 : 2 : 3 : 5 : 8 : ... Նույնը կարելի է գրել նաև ցուցակի սպեցիֆիկատորներ օգտագործելիս, fibs = 0 : 1 : [a + b | (a,b) <- zip fibs (tail fibs)]
կամ GHC կոմպիլյատորում ներդրված Haskell լեզվի ընդլայնում (զուգահեռ ցանկի սահմանիչներ,անգլ.՝ parallel list comprehensions ): fibs = 0 : 1 : [a + b | a <- fibs
| b <- tail fibs]
կամ օգտագործելով ուղղակիորեն ինքնահղում գեներացնող ֆունկցիա . fibs = 0 : 1 : next fibs
where
next (a: t@(b:_)) = (a+b) : next t
Պարզ թվերԱյս օրինակները ցույց են տալիս, թե ինչպես կարող են օգտագործվել ցուցակի արտահայտությունները ( ցուցակի գեներատորներ ): Բոլոր պարզ թվերը սովորական եղանակով գտնելու իրականացում ( յուրաքանչյուր թվի պարզության ստուգում ). -- ընդհանուր սահմանում (բոլոր բնական թվերը > 1, որոնք պարզ են)
primeNums = 2 : [n | n <- [3..], isPrime n]
-- Թիվն պարզ է, եթե չունի (պարզ) գործակից
isPrime n = foldr (\p r-> p*p>n || (rem n p /= 0 && r)) True primeNums
կամ օգտագործելով Էրատոսթենեսի մաղը, իր նախատիպային, անարդյունավետ տարբերակով, primes = (map head . scanl minus [2..] . map (\p -> [p, p+p..])) primes
կամ արդյունավետ՝ կոմպոզիտային թվերի հոսքերի նախնական կասկադային համադրմամբ primes = 2 : _Y ((3:) . minus [5,7..] . unionAll . map (\p -> [p*p, p*p+2*p..]))
where
_Y g = g (_Y g)
unionAll ((x:xs):t) = x : union xs (unionAll (pairs t))
pairs ((x:xs):ys:t) = (x : union xs ys) : pairs t
կամ հատված առ հատված, զանգվածներով, import Data.Array
import Data.List (tails, inits)
ps = 2 : [n | (r:q:_, px) <- (zip . tails . (2:) . map (^2)) ps (inits ps),
(n,True) <- assocs (
accumArray (\_ _ -> False) True (r+1,q-1)
[(m,()) | p <- px,
let s = div (r+p) p * p, m <- [s,s+p..q-1]] )]
օգտագործելով կանոնական ֆունկցիաները union (x:xs) (y:ys) = case compare x y of
LT -> x : union xs (y:ys)
EQ -> x : union xs ys
GT -> y : union (x:xs) ys
union a b = a ++ b
minus (x:xs) (y:ys) = case compare x y of
LT -> x : minus xs (y:ys)
EQ -> minus xs ys
GT -> minus (x:xs) ys
minus a b = a
Թվային ինտեգրումԹվային ինտեգրում սեղանի մեթոդով: trapezeIntegrate f a b n =
((sum $ map f [a + h, a + 2*h .. b - h]) + t) * h
where
t = (f a + f b)/2
h = (b - a) / n
main = do
print $ trapezeIntegrate (\x -> x*sin x) 0 (2*pi) 100
-- Արդյունք: -6.281118086046067
Պալինդրոմի ստուգումՍտորև բերված օրինակը ցույց է տալիս,ինչպես աշխատել Unicode տողերի հետ: import Data.Char (toLower, isAlpha)
palindrom :: [Char] -> Bool
palindrom s =
norm == reverse norm
where norm = map toLower $ filter isAlpha $ s
test :: [Char] -> IO ()
test s =
putStrLn $ s ++ ": " ++ show (palindrom s)
main = do
test "А в Енисее — синева"
test "А роза упала на лапу Азора"
test "Не роза упала на лапу Азора"
test "Мир как Рим"
test "Мир не Рим"
test "I prefer Pi"
test "حوت فمه مفتوح"
test "Ne mateno, bone tamen"
-- Вывод:
-- А в Енисее — синева: True
-- А роза упала на лапу Азора: True
-- Не роза упала на лапу Азора: False
-- Мир как Рим: True
-- Мир не Рим: False
-- I prefer Pi: True
-- حوت فمه مفتوح: True
-- Ne mateno, bone tamen: True
Հավելվածներ, գրված Haskell ծրագրավորման լեզվովԿոմերցիոն ծրագրերԼեզուն որոշակի տարածում ձեռք է բերել առևտրային միջավայրում[21], ինչին, մասնավորապես, նպաստել է համայնքի ավանդույթը՝ արտոնագրերով գրադարաններ թողարկելու համար (ազատ հասանելի գրադարանների ավելի քան 70%-ը բաշխվում է BSD-ի, MIT-ի լիցենզիաների պայմաններով կամ գտնվում են հանրային սեփականություն): Haskell-ում իրականացվող առևտրային նախագծերից են Bluespec SystemVerilog (կիսահաղորդչային սխեմաների նախագծման և ստուգման համար նախատեսված, Haskell լեզվի ընդլայնում)[22], Cryptol (գաղտնագրման ալգորիթմների մշակման և ստուգման լեզու, իրականացված Haskell ծրագրավորման լեզվով): Առաջին պաշտոնապես հաստատված seL4 միկրոմիջուկը գրվել է նաև Haskell–ի միջոցով: Haskell-ը ակտիվորեն օգտագործվում է ֆինանսական ծրագրավորման, ռիսկերի վերլուծության և որոշումների աջակցման համակարգերի ոլորտում: Haskell-ը օգտագործվում է քաղաքի լանդշաֆտային գեներատորի մշակողների կողմից խաղերի և Gamr7 սիմուլյացիաների համար[23] : Առևտրային կազմակերպություններում (ներառյալ ԱՊՀ երկրներում) մասնավոր տեղեկատվական համակարգերի զարգացման համար ևս օգտագործվել է Haskell ծրագրավորման լեզուն[24] : Բաց կոդով հավելվածներԲաց կոդով գրադարանների և Haskell-ով գրված հավելվածների զգալի մասը հասանելի է Hackage-ի արխիվում: Դրանք ներառում են համընդհանուր նշագրման փոխարկիչ Pandoc, emacs-ի նմանվող տեքստային խմբագրիչ Yi և ինտեգրված զարգացման միջավայր Leksah : Համակարգի զարգացումներից են բաշխված տարբերակների կառավարման համակարգը Darcs-ը, House օպերացիոն համակարգը և խճանկարային պատուհանների կառավարիչ Xmonad-ը : GHC կոմպիլյատորը հաճախ ծառայում է որպես փորձնական հարթակ՝ ֆունկցիոնալ ծրագրավորման և օպտիմալացման նոր հնարավորությունների փորձարկման համար: Միևնույն ժամանակ, Agda, Curry, լեզուների կազմողները, ինչպես նաև Perl 6 Pugs լեզվի առաջին կոմպիլյատորն ու թարգմանիչը (ստեղծվել է ընդամենը մեկ ամսում), գրվել են Haskell-ով։ Ծանոթագրություններ
Գրականություն
Արտաքին հղումներ
|