AMcoder - javascript, python, java, html, php, sql

Ցանկի երկարությունը առանց Haskell-ի երկարության ֆունկցիայի

Ես ուզում եմ տեսնել, թե որքան երկար է ցուցակը, բայց առանց length ֆունկցիայի օգտագործման: Ես գրել եմ այս ծրագիրը և այն չի աշխատում: Միգուցե կարող եք ասել, թե ինչու: Շնորհակալություն

let y = 0
main = do
  list (x:xs) = list (xs)
  y++

list :: [Integer] -> Integer
list [] = y


Պատասխանները:


1

Ձեր ծրագիրը բավականին «հրամայական» տեսք ունի. դուք սահմանում եք y փոփոխականը, այնուհետև ինչ-որ կերպ գրում եք do, որը կանչում է (?) list ֆունկցիան (?), որն ինքնաբերաբար կարծես «վերադարձնում է y»-ը և այնուհետև դուք ուզում եմ ավելացնել y:

Haskell (և առավել ֆունկցիոնալ և դեկլարատիվ) լեզուներն այդպես չեն աշխատում.

  • Դեկլարատիվ լեզվով դուք սահմանում եք փոփոխականը միայն մեկ անգամ, արժեքը սահմանելուց հետո, սովորաբար դրա արժեքը փոխելու հնարավորություն չկա,
  • Haskell-ում do-ը սովորաբար օգտագործվում է մոնադների համար, մինչդեռ lengthմաքուր ֆունկցիա է,
  • let-ը շարահյուսական կոնստրուկցիա է՝ արտահայտության շրջանակում փոփոխական սահմանելու համար,
  • ...

Haskell-ը (կամ որևէ ֆունկցիոնալ լեզու) ծրագրավորելու համար դուք պետք է «մտածեք ֆունկցիոնալ». մտածեք, թե ինչպես կլուծեիք խնդիրը մաթեմատիկական եղանակով՝ օգտագործելով միայն ֆունկցիաները:

Մաթեմատիկայի մեջ դուք կասեք, որ [] դատարկ ցուցակը հստակորեն ունի 0 երկարություն: Ավելին, եթե ցուցակը դատարկ չէ, կա առաջին տարրը («գլուխը») և մնացած տարրերը («պոչը»): Այդ դեպքում արդյունքը մեկ գումարած պոչի երկարությունն է։ Մենք կարող ենք դա վերածել մաթեմատիկական արտահայտության մեջ, ինչպիսին է.

«LaTeX»

Այժմ մենք կարող ենք հեշտությամբ թարգմանել այդ գործառույթը հետևյալ Haskell կոդի մեջ.

ownLength :: [a] -> Int
ownLength [] = 0
ownLength (_:xs) = 1 + ownLength xs

Այժմ Haskell-ում սովորաբար օգտագործվում են կուտակիչներ՝ պոչի ռեկուրսիա կատարելու համար. դուք փոխանցում եք պարամետր ռեկուրսիվ զանգերի միջոցով և ամեն անգամ, երբ թարմացնում եք: փոփոխականը։ Երբ հասնում եք ձեր ռեկուրսիայի ավարտին, դուք վերադառնում եք, երբեմն որոշ հետմշակումից հետո, կուտակիչ:

Այս դեպքում կուտակիչը կլինի մինչ այժմ տեսած երկարությունը, այնպես որ կարող եք գրել.

ownLength :: [a] -> Int
ownLength = ownLength' 0
    where ownLength' a [] = a
          ownLength' a (_:xs) = ownLength' (a+1) xs
16.05.2017
  • Շնորհակալություն! Ես գիտեի, որ դա չափազանց հրամայական է, բայց ես չէի կարող հասնել եզրափակիչ՝ առանց այսպես անելու: Շնորհակալություն ևս մեկ անգամ: 16.05.2017
  • Իհարկե, քանի որ ցուցակներն իսկապես մոնադ են, դուք կարող եք սահմանել lengthը որպես մոնադիկ գործողություն. length xs = sum $ do {xs; return 1} 16.05.2017

  • 2

    Կարծես դու դեռ մտածում ես հրամայական ձևով (ոչ ֆունկցիոնալ ձևով): Օրինակ:

    • դուք փորձում եք փոխել «փոփոխականի» արժեքը (այսինքն՝ y++)
    • դուք փորձում եք օգտագործել «գլոբալ փոփոխական» (այսինքն y) list ֆունկցիայի մարմնում

    Ահա ձեր խնդրի հնարավոր լուծումը.

    main = print $ my_length [1..10]
    
    my_length :: [Integer] -> Integer
    my_length [] = 0
    my_length (_:xs) = 1 + my_length xs
    

    Կարող եք նաև գործարկել այս կոդը այստեղ՝ http://ideone.com/mjUwL9:

    Խնդրում ենք նաև նկատի ունենալ, որ կարիք չկա պահանջելու, որ ձեր ցուցակը բաղկացած լինի Integer արժեքներից: Փաստորեն, դուք կարող եք ստեղծել ձեր ֆունկցիայի շատ ավելի «ագնոստիկ» տարբերակը՝ օգտագործելով հետևյալ հայտարարությունը.

    my_length :: [a] -> Integer
    

    Այս ֆունկցիայի իրականացումը կախված չէ ցանկի տարրերի տեսակից, ուստի այն կարող եք օգտագործել ցանկացած տեսակի ցանկի համար: Ի հակադրություն, դուք չեք կարող այդքան լիբերալ լինել, օրինակ, my_sum ֆունկցիայի համար (պոտենցիալ ֆունկցիա, որը հաշվարկում է տվյալ ցանկի տարրերի գումարը): Այս իրավիճակում դուք պետք է սահմանեք, որ ձեր ցուցակը բաղկացած է որոշ թվային տիպի տարրերից:

    Վերջում ես ուզում եմ ձեզ մի ֆանտաստիկ գիրք առաջարկել Haskell ծրագրավորման մասին՝ http://learnyouahaskell.com/chapters.

    16.05.2017
  • Այո, դու ճիշտ ես: Ես գիտեի, որ դա հրամայական է, բայց այլ կերպ չէի կարող հասնել մինչև վերջ: Ես արդեն սկսել եմ գիրքը։ 16.05.2017


  • 4

    Հավանաբար ամենապարզ ձևը բոլոր տարրերը 1-ի վերածելն է, այնուհետև նոր տարրերը գումարելը.

    sum . map (const 1)
    

    Ավելացված արագության համար.

    foldl' (+) 0 . map (const 1)
    
    27.06.2018
    Նոր նյութեր

    Օգտագործելով Fetch Vs Axios.Js-ը՝ HTTP հարցումներ կատարելու համար
    JavaScript-ը կարող է ցանցային հարցումներ ուղարկել սերվեր և բեռնել նոր տեղեկատվություն, երբ դա անհրաժեշտ լինի: Օրինակ, մենք կարող ենք օգտագործել ցանցային հարցումը պատվեր ներկայացնելու,..

    Տիրապետել հանգստության արվեստին. մշակողի ուղեցույց՝ ճնշման տակ ծաղկելու համար
    Տիրապետել հանգստության արվեստին. մշակողի ուղեցույց՝ ճնշման տակ ծաղկելու համար Ինչպե՞ս հանգստացնել ձեր միտքը և աշխատեցնել ձեր պրոցեսորը: Ինչպես մնալ հանգիստ և զարգանալ ճնշման տակ...

    Մեքենայի ուսուցում բանկային և ֆինանսների ոլորտում
    Բարդ, խելացի անվտանգության համակարգերը և հաճախորդների սպասարկման պարզեցված ծառայությունները բիզնեսի հաջողության բանալին են: Ֆինանսական հաստատությունները, մասնավորապես, պետք է առաջ մնան կորի..

    Ես AI-ին հարցրի կյանքի իմաստը, այն ինչ ասում էր, ցնցող էր:
    Այն պահից ի վեր, երբ ես իմացա Արհեստական ​​ինտելեկտի մասին, ես հիացած էի այն բանով, թե ինչպես է այն կարողանում հասկանալ մարդկային նորմալ տեքստը, և այն կարող է առաջացնել իր սեփական արձագանքը դրա..

    Ինչպես սովորել կոդավորումը Python-ում վագրի պես:
    Սովորելու համար ծրագրավորման նոր լեզու ընտրելը բարդ է: Անկախ նրանից, թե դուք սկսնակ եք, թե առաջադեմ, դա օգնում է իմանալ, թե ինչ թեմաներ պետք է սովորել: Ծրագրավորման լեզվի հիմունքները, դրա..

    C++-ի օրական բիթ(ե) | Ամենաերկար պալինդրոմային ենթաշարը
    C++ #198-ի ամենօրյա բիթ(ե), Ընդհանուր հարցազրույցի խնդիր. Ամենաերկար պալինդրոմային ենթատող: Այսօր մենք կանդրադառնանք հարցազրույցի ընդհանուր խնդրին. Ամենաերկար palindromic substring...

    Kydavra ICAReducer՝ ձեր տվյալների ծավալայինությունը նվազեցնելու համար
    Ի՞նչ է ICAReducer-ը: ICAReducer-ն աշխատում է հետևյալ կերպ. այն նվազեցնում է նրանց միջև բարձր փոխկապակցված հատկանիշները մինչև մեկ սյունակ: Բավականին նման է PCAreducer-ին, չնայած այն..