F # تعليمي: كيفية إنشاء تطبيق F # كامل المكدس

نشرت: 2022-03-11

في السنوات الأخيرة ، اكتسبت البرمجة الوظيفية سمعة باعتبارها نموذجًا صارمًا ومنتجًا بشكل خاص. لا تكتسب لغات البرمجة الوظيفية الاهتمام داخل مجتمعات المبرمجين فحسب ، بل بدأت العديد من الشركات الكبيرة أيضًا في استخدام لغات البرمجة الوظيفية لحل المشكلات التجارية.

على سبيل المثال ، بدأت Walmart في استخدام Clojure ، وهي لهجة Lisp الوظيفية المستندة إلى JVM ، للبنية التحتية للتسجيل ؛ Jet.com ، وهي منصة كبيرة للتجارة الإلكترونية (مملوكة الآن من قبل Walmart) ، تستخدم F # لبناء معظم خدماتها الصغيرة ؛ و Jane Street ، وهي شركة تجارية مملوكة ملكية ، تستخدم بشكل أساسي OCaml لبناء الخوارزميات الخاصة بهم.

اليوم ، سوف نستكشف برمجة F #. F # هي إحدى لغات البرمجة الوظيفية التي تشهد اعتمادًا متزايدًا نظرًا لمرونتها وتكاملها القوي مع .NET والجودة العالية للأدوات المتاحة. لأغراض هذا البرنامج التعليمي F # ، سنقوم ببناء خادم ويب بسيط وتطبيق جوال ذي صلة باستخدام F # فقط لكل من الواجهة الأمامية والخلفية.

لماذا تختار F # وما هو استخدام F #؟

بالنسبة لمشروع اليوم ، لن نستخدم أي شيء سوى F #. هناك عدة أسباب لتفضيل F # كلغة نختارها:

  • تكامل .NET: يتمتع F # بتكامل وثيق للغاية مع بقية عالم .NET وبالتالي فهو يتمتع بسهولة الوصول إلى نظام بيئي كبير من المكتبات المدعومة جيدًا والموثقة بدقة لحل مجموعة واسعة من مهام البرمجة.
  • الإيجاز: F # موجزة للغاية بسبب نظام الاستدلال النوعي القوي والصيغة المقتضبة. غالبًا ما يمكن حل مهام البرمجة بشكل أكثر أناقة باستخدام F # بدلاً من C # أو Java. يمكن أن يظهر رمز F # مبسطًا جدًا عن طريق المقارنة.
  • أدوات المطور: يتمتع F # بتكامل قوي في Visual Studio ، وهو أحد أفضل IDEs لنظام .NET البيئي. بالنسبة لأولئك الذين يعملون على أنظمة أساسية بخلاف Windows ، هناك وفرة من المكونات الإضافية في كود الاستوديو المرئي. هذه الأدوات تجعل البرمجة في F # مثمرة للغاية.

يمكنني متابعة فوائد استخدام F # ، ولكن دون مزيد من اللغط ، دعنا نتعمق!

الفكرة وراء برنامجنا التعليمي لـ F #

في الولايات المتحدة ، هناك قول مأثور: "إنها الخامسة في مكان ما" .

في بعض أنحاء العالم ، تكون الساعة 5:00 مساءً هي أقرب وقت يكون فيه من المقبول اجتماعياً تناول مشروب أو فنجان شاي تقليدي.

اليوم ، سنبني تطبيقًا بناءً على هذا المفهوم. سننشئ تطبيقًا يبحث في مختلف المناطق الزمنية ، في أي وقت ، ويكتشف مكان الساعة الخامسة ، ويقدم هذه المعلومات للمستخدم.

النهاية الخلفية

إعداد خادم الويب

سنبدأ بجعل الخدمة الخلفية التي تؤدي وظيفة البحث عن المنطقة الزمنية. سوف نستخدم Suave.IO لبناء JSON API.

توضيح تعليمي # F: إعداد خادم الويب

Suave.IO هو إطار عمل ويب سهل الاستخدام مع خادم ويب خفيف الوزن يسمح بتشفير تطبيقات الويب البسيطة بسرعة كبيرة.

للبدء ، انتقل إلى Visual Studio وابدأ مشروع تطبيق F # Console جديد. إذا لم يكن هذا الخيار متاحًا لك ، فقد تحتاج إلى تثبيت وظيفة F # باستخدام Visual Studio Installer. اسم المشروع "FivePM". بمجرد إنشاء التطبيق الخاص بك ، يجب أن ترى شيئًا مثل هذا:

 [<EntryPoint>] let main argv = printfn "%A" argv 0 // return an integer exit code

هذا جزء بسيط جدًا من رمز البدء الذي يطبع الوسيطة ويخرج برمز الحالة 0. لا تتردد في تغيير بيان الطباعة وتجربة وظائف مختلفة من الكود. المُنسق "٪ A" هو مُنسق خاص يقوم بطباعة تمثيل السلسلة لأي نوع تقوم بتمريره ، لذلك لا تتردد في طباعة الأعداد الصحيحة أو العوامات أو حتى الأنواع المعقدة. بمجرد أن تشعر بالراحة مع بناء الجملة الأساسي ، فقد حان الوقت لتثبيت Suave.

أسهل طريقة لتثبيت Suave هي من خلال مدير الحزم NuGet. انتقل إلى مشروع -> إدارة حزم NuGet ، وانقر فوق علامة التبويب استعراض. ابحث عن Suave وانقر فوق تثبيت. بمجرد قبول الحزم المراد تثبيتها ، يجب أن تكون جاهزًا تمامًا! عد الآن إلى شاشة program.fs الخاصة بك ونحن جاهزون لبدء بناء الخادم.

لبدء استخدام Suave ، سنحتاج إلى استيراد الحزمة أولاً. في الجزء العلوي من برنامجك ، اكتب العبارات التالية:

 open Suave open Suave.Operators open Suave.Filters open Suave.Successful

سيؤدي هذا إلى استيراد الحزم الأساسية المطلوبة لبناء خادم ويب أساسي. الآن استبدل الكود الرئيسي بما يلي ، والذي يحدد تطبيقًا بسيطًا ويقدمه على المنفذ 8080:

 [<EntryPoint>] let main argv = // Define the port where you want to serve. We'll hardcode this for now. let port = 8080 // create an app config with the port let cfg = { defaultConfig with bindings = [ HttpBinding.createSimple HTTP "0.0.0.0" port]} // We'll define a single GET route at the / endpoint that returns "Hello World" let app = choose [ GET >=> choose [ path "/" >=> request (fun _ -> OK "Hello World!")] ] // Now we start the server startWebServer cfg app 0

يجب أن تبدو الشفرة واضحة جدًا ، حتى إذا لم تكن معتادًا على بناء جملة F # أو طريقة Suave لتعريف معالجات المسار ، يجب أن يكون الكود قابلاً للقراءة إلى حد ما. بشكل أساسي ، يعود تطبيق الويب بحالة 200 و "Hello World!" السلسلة عندما يتم الضغط عليها مع طلب GET على المسار "/". انطلق وقم بتشغيل التطبيق (F5 في Visual Studio) وانتقل إلى localhost: 8080 ، وسترى "Hello World!" في نافذة المتصفح الخاص بك.

إعادة بناء كود الخادم

الآن لدينا خادم ويب! لسوء الحظ ، لا تعمل كثيرًا - لذلك دعونا نعطيها بعض الوظائف! أولاً ، دعنا ننقل وظائف خادم الويب إلى مكان آخر حتى نبني بعض الوظائف دون القلق بشأن خادم الويب (سنقوم بتوصيله بخادم الويب لاحقًا). حدد وظيفة منفصلة على النحو التالي:

 // We'll use argv later :) let runWebServer argv = // Define the port where you want to serve. We'll hardcode this for now. let port = 8080 // create an app config with the port let cfg = { defaultConfig with bindings = [ HttpBinding.createSimple HTTP "0.0.0.0" port]} // We'll define a single GET route at the / endpoint that returns "Hello World" let app = choose [ GET >=> choose [ path "/" >=> request (fun _ -> OK "Hello World!")] ] // Now we start the server startWebServer cfg app

الآن قم بتغيير الوظيفة الرئيسية إلى ما يلي وتأكد من أننا فعلناها بشكل صحيح.

 [<EntryPoint>] let main argv = runWebServer argv 0

اضغط على F5 و "Hello World!" يجب أن يعمل الخادم كما كان من قبل.

الحصول على المناطق الزمنية

الآن دعونا نبني الوظيفة التي تحدد المنطقة الزمنية حيث تكون الساعة الخامسة. نريد كتابة بعض التعليمات البرمجية للتكرار عبر جميع المناطق الزمنية وتحديد المنطقة الزمنية الأقرب إلى الساعة 5:00 مساءً.

إحضار رسم توضيحي للمناطق الزمنية

علاوة على ذلك ، لا نريد حقًا إعادة منطقة زمنية قريبة جدًا من الساعة 5:00 مساءً ولكنها تسبقها قليلاً (على سبيل المثال 4:58 مساءً) لأنه ، لأغراض هذا العرض التوضيحي ، فإن الفرضية هي أنه لا يمكن أن يكون قبل 5 : 00 مساءً ، ولكن قريبًا.

لنبدأ بالحصول على قائمة المناطق الزمنية. في F # هذا سهل للغاية لأنه يتكامل بشكل جيد مع C #. أضف "نظام مفتوح" في الجزء العلوي ، وقم بتغيير تطبيق F # الخاص بك إلى هذا:

 [<EntryPoint>] let main argv = // This gets all the time zones into a List-like object let tzs = TimeZoneInfo.GetSystemTimeZones() // Now we iterate through the list and print out the names of the timezones for tz in tzs do printfn "%s" tz.DisplayName 0

قم بتشغيل التطبيق وسترى في وحدة التحكم الخاصة بك قائمة بجميع المناطق الزمنية وإزاحاتها واسم عرضها.

إنشاء واستخدام نوع مخصص

الآن بعد أن أصبح لدينا قائمة بالمناطق الزمنية ، يمكننا تحويلها إلى نوع بيانات مخصص يكون أكثر إفادة لنا ، شيء يحتوي على معلومات مثل تعويض التوقيت العالمي المنسق (UTC) ، والتوقيت المحلي ، ومدى المسافة من الساعة 5:00 مساءً بالتوقيت المحلي ، إلخ. لتحقيق هذه الغاية ، دعنا نحدد نوعًا مخصصًا ، أعلى وظيفتك الرئيسية مباشرةً:

 type TZInfo = {tzName: string; minDiff: float; localTime: string; utcOffset: float}

الآن يمكننا التحويل ومعلومات المنطقة الزمنية التي حصلنا عليها من الخطوة الأخيرة إلى قائمة كائنات TZInfo هذه. قم بتغيير وظيفتك الرئيسية على هذا النحو:

 [<EntryPoint>] let main argv = // This gets all the time zones into a List-like object let tzs = TimeZoneInfo.GetSystemTimeZones() // List comprehension + type inference allows us to easily perform conversions let tzList = [ for tz in tzs do // convert the current time to the local time zone let localTz = TimeZoneInfo.ConvertTime(DateTime.Now, tz) // Get the datetime object if it was 5:00pm let fivePM = DateTime(localTz.Year, localTz.Month, localTz.Day, 17, 0, 0) // Get the difference between now local time and 5:00pm local time. let minDifference = (localTz - fivePM).TotalMinutes yield { tzName=tz.StandardName; minDiff=minDifference; localTime=localTz.ToString("hh:mm tt"); utcOffset=tz.BaseUtcOffset.TotalHours; } ] printfn "%A" tzList.Head 0

ويجب أن ترى كائن tzInfo لوقت Dateline القياسي مطبوعًا على شاشتك.

الفرز والتصفية والأنابيب ، يا إلهي!

الآن بعد أن أصبح لدينا قائمة بكائنات tzInfo ، يمكننا تصفية وفرز هذه الكائنات للعثور على المنطقة الزمنية حيث تكون 1) بعد الساعة 5:00 مساءً و 2) الأقرب إلى 5:00 مساءً من المناطق الزمنية في 1). قم بتغيير وظيفتك الرئيسية على النحو التالي:

 [<EntryPoint>] let main argv = // This gets all the time zones into a List-like object let tzs = TimeZoneInfo.GetSystemTimeZones() // List comprehension + type inference allows us to easily perform conversions let tzList = [ for tz in tzs do // convert the current time to the local time zone let localTz = TimeZoneInfo.ConvertTime(DateTime.Now, tz) // Get the datetime object if it was 5:00pm let fivePM = DateTime(localTz.Year, localTz.Month, localTz.Day, 17, 0, 0) // Get the difference between now local time and 5:00pm local time. let minDifference = (localTz - fivePM).TotalMinutes yield { tzName=tz.StandardName; minDiff=minDifference; localTime=localTz.ToString("hh:mm tt"); utcOffset=tz.BaseUtcOffset.TotalHours; } ] // We use the pipe operator to chain functiona calls together let closest = tzList // filter so that we only get tz after 5pm |> List.filter (fun (i:TZInfo) -> i.minDiff >= 0.0) // sort by minDiff |> List.sortBy (fun (i:TZInfo) -> i.minDiff) // Get the first item |> List.head printfn "%A" closest

والآن يجب أن نحصل على المنطقة الزمنية التي نبحث عنها.

إعادة هيكلة أداة إنشاء المنطقة الزمنية وفقًا لوظيفتها الخاصة

الآن دعنا نعيد تشكيل الكود إلى وظيفته الخاصة حتى نتمكن من استخدامه لاحقًا. حدد وظيفة على النحو التالي:

 // the function takes uint as input, and we represent that as "()" let getClosest () = // This gets all the time zones into a List-like object let tzs = TimeZoneInfo.GetSystemTimeZones() // List comprehension + type inference allows us to easily perform conversions let tzList = [ for tz in tzs do // convert the current time to the local time zone let localTz = TimeZoneInfo.ConvertTime(DateTime.Now, tz) // Get the datetime object if it was 5:00pm let fivePM = DateTime(localTz.Year, localTz.Month, localTz.Day, 17, 0, 0) // Get the difference between now local time and 5:00pm local time. let minDifference = (localTz - fivePM).TotalMinutes yield { tzName=tz.StandardName; minDiff=minDifference; localTime=localTz.ToString("hh:mm tt"); utcOffset=tz.BaseUtcOffset.TotalHours; } ] // We use the pipe operator to chain function calls together tzList // filter so that we only get tz after 5pm |> List.filter (fun (i:TZInfo) -> i.minDiff >= 0.0) // sort by minDiff |> List.sortBy (fun (i:TZInfo) -> i.minDiff) // Get the first item |> List.head And our main function can just be: [<EntryPoint>] let main argv = printfn "%A" <| getClosest() 0

قم بتشغيل الكود وسترى نفس الإخراج كما كان من قبل.

JSON ترميز بيانات الإرجاع

الآن بعد أن أصبح بإمكاننا الحصول على بيانات المنطقة الزمنية ، يمكننا تحويل المعلومات إلى JSON وتقديمها من خلال تطبيقنا. هذا بسيط للغاية ، بفضل حزمة JSON.NET من NewtonSoft. ارجع إلى مدير الحزم في NuGet وابحث عن Newtonsoft.Json ، وقم بتثبيت الحزمة. عد الآن إلى Program.fs وقم بإجراء تغيير بسيط على وظيفتنا الرئيسية:

 [<EntryPoint>] let main argv = printfn "%s" <| JsonConvert.SerializeObject(getClosest()) 0

قم بتشغيل الكود الآن وبدلاً من كائن TZInfo ، يجب أن ترى JSON مطبوعًا على وحدة التحكم الخاصة بك.

توصيل معلومات المنطقة الزمنية بواجهة برمجة تطبيقات JSON

من السهل جدًا توصيل هذا بواجهة برمجة تطبيقات JSON الخاصة بنا. ما عليك سوى إجراء التغييرات التالية على وظيفة runWebServer الخاصة بك:

 // We'll use argv later :) let runWebServer argv = // Define the port where you want to serve. We'll hardcode this for now. let port = 8080 // create an app config with the port let cfg = { defaultConfig with bindings = [ HttpBinding.createSimple HTTP "0.0.0.0" port]} // We'll define a single GET route at the / endpoint that returns "Hello World" let app = choose [ GET >=> choose [ // We are getting the closest time zone, converting it to JSON, then setting the MimeType path "/" >=> request (fun _ -> OK <| JsonConvert.SerializeObject(getClosest())) >=> setMimeType "application/json; charset=utf-8" ] ] // Now we start the server startWebServer cfg app

قم بتشغيل التطبيق ، وانتقل إلى المضيف المحلي: 8080. يجب أن ترى JSON في نافذة المتصفح.

نشر الخادم

الآن بعد أن أصبح لدينا خادم JSON API ، يمكننا نشره بحيث يمكن الوصول إليه على الإنترنت. إحدى أسهل الطرق لنشر هذا التطبيق هي من خلال خدمة تطبيقات Microsoft Azure والتي يمكن فهمها على أنها خدمة IIS مُدارة. للنشر في خدمة Azure App ، توجه إلى https://portal.azure.com وانتقل إلى خدمة التطبيقات. قم بإنشاء تطبيق جديد ، وانتقل إلى مركز النشر في البوابة الإلكترونية. يمكن أن تكون البوابة مربكة بعض الشيء إذا كانت هذه هي المرة الأولى لك ، لذلك إذا كنت تواجه مشكلة فتأكد من استشارة أحد البرامج التعليمية العديدة المتوفرة حول استخدام خدمة التطبيقات.

يجب أن تشاهد مجموعة متنوعة من الخيارات للنشر. يمكنك استخدام أي شيء تريده ، ولكن من أجل البساطة ، يمكننا استخدام خيار FTP.

تبحث خدمة التطبيقات عن ملف web.config في جذر التطبيق الخاص بك لمعرفة كيفية تشغيل التطبيق الخاص بك. نظرًا لأن خادم الويب الخاص بنا هو تطبيق وحدة تحكم أساسي ، يمكننا نشر التطبيق والتكامل مع خادم IIS باستخدام HttpPlatformHandler. في Visual Studio ، أضف ملف XML إلى مشروعك وقم بتسميته web.config. املأه بـ XML التالي:

 <?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <handlers> <remove name="httpplatformhandler" /> <add name="httpplatformhandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified"/> </handlers> <httpPlatform stdoutLogEnabled="true" stdoutLogFile="suave.log" startupTimeLimit="20" processPath=".\publish\FivePM.exe" arguments="%HTTP_PLATFORM_PORT%"/> </system.webServer> </configuration>

اتصل بخادم FTP باستخدام بيانات الاعتماد التي تم الحصول عليها من مركز النشر (ستحتاج إلى النقر فوق خيار FTP). انقل web.config إلى مجلد wwwroot لموقع FTP لخدمة التطبيق.

نريد الآن إنشاء تطبيقنا ونشره ، ولكن قبل ذلك ، نحتاج إلى إجراء تغيير بسيط على رمز الخادم. انتقل إلى وظيفة RunServer الخاصة بك وقم بتغيير الأسطر الثلاثة الأولى إلى ما يلي:

 let runWebServer (argv:string[]) = // Define the port where you want to serve. We'll hardcode this for now. let port = if argv.Length = 0 then 8080 else (int argv.[0])

مما يسمح للتطبيق بالنظر إلى الوسيطة التي تم تمريرها واستخدام الوسيطة الأولى كرقم المنفذ بدلاً من جعل المنفذ مشفرًا إلى 8080. في تكوين الويب ، نقوم بتمرير٪ HTTP_PLATFORM_PORT٪ كأول وسيطة ، لذلك نحن يجب تعيين.

أنشئ التطبيق في وضع الإصدار ، وانشر التطبيق ، وانسخ المجلد المنشور إلى wwwroot. أعد تشغيل التطبيق وسترى نتيجة JSON API على موقع *.azurewebsites.net .

الآن تم نشر تطبيقنا!

الواجهة الأمامية

رسم توضيحي للواجهة الأمامية #

الآن بعد أن تم نشر الخادم ، يمكننا إنشاء واجهة أمامية. بالنسبة للواجهة الأمامية ، سنقوم بإنشاء تطبيق Android باستخدام Xamarin و F #. تتمتع هذه المجموعة ، مثل بيئتنا الخلفية ، بتكامل عميق مع Visual Studio. بالطبع ، يدعم النظام البيئي F # عددًا لا بأس به من خيارات التطوير الأمامية (WebSharper ، Fable / Elmish ، Xamarin.iOS ، DotL Liquid وما إلى ذلك) ، ولكن من أجل الإيجاز ، سنطور فقط باستخدام Xamarin.Android لهذا المنشور ونترك لهم للوظائف المستقبلية.

اعداد

لإعداد تطبيق Android ، ابدأ مشروعًا جديدًا وحدد خيار Xamarin Android. تأكد من تثبيت أدوات تطوير Android لديك. بمجرد إعداد المشروع ، يجب أن ترى شيئًا كهذا في ملف الكود الرئيسي الخاص بك.

 [<Activity (Label = "FivePMFinder", MainLauncher = true, Icon = "@mipmap/icon")>] type MainActivity () = inherit Activity () let mutable count:int = 1 override this.OnCreate (bundle) = base.OnCreate (bundle) // Set our view from the "main" layout resource this.SetContentView (Resources.Layout.Main) // Get our button from the layout resource, and attach an event to it let button = this.FindViewById<Button>(Resources.Id.myButton) button.Click.Add (fun args -> button.Text <- sprintf "%d clicks!" count count <- count + 1 )

هذا هو رمز البداية لـ F # Android Xamarin. يتتبع الكود حاليًا عدد المرات التي تم فيها النقر فوق الزر ويعرض قيمة العد الحالية. يمكنك أن ترى أنه يعمل عن طريق الضغط على F5 لتشغيل المحاكي وبدء تشغيل التطبيق في وضع التصحيح.

إضافة مكونات واجهة المستخدم

دعنا نضيف بعض مكونات واجهة المستخدم ونجعلها أكثر فائدة. افتح المورد / التخطيطات وانتقل إلى Main.axml.

يجب أن تشاهد تمثيلًا مرئيًا لتخطيط النشاط الرئيسي. يمكنك تعديل عناصر واجهة المستخدم المختلفة بالنقر فوق العناصر. يمكنك إضافة عناصر بالانتقال إلى صندوق الأدوات واختيار العنصر الذي تريد إضافته. أعد تسمية الزر وأضف عرض نصي أسفل الزر. يجب أن يبدو تمثيل XML لـ AXML مشابهًا لما يلي:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:andro android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android: android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/fivePM" /> <TextView android:text="" android:textAppearance="?android:attr/textAppearanceMedium" android:layout_width="match_parent" android:layout_height="wrap_content" android: /> </LinearLayout>

يشير AXML إلى ملف مورد السلاسل ، لذا افتح الموارد / القيم / strings.xml وقم بإجراء التغييرات التالية:

 <?xml version="1.0" encoding="utf-8"?> <resources> <string name="fivePM">It\'s 5PM Somewhere!</string> <string name="app_name">5PM Finder</string> </resources>

الآن قمنا ببناء AXML للواجهة الأمامية. الآن دعنا نربطه ببعض التعليمات البرمجية. انتقل إلى MainActivity.fs وقم بإجراء التغييرات التالية على وظيفة onCreate الخاصة بك:

 base.OnCreate (bundle) // Set our view from the "main" layout resource this.SetContentView (Resources.Layout.Main) // Get our button from the layout resource, and attach an event to it let button = this.FindViewById<Button>(Resources.Id.myButton) let txtView = this.FindViewById<TextView>(Resources.Id.textView1); button.Click.Add (fun args -> let webClient = new WebClient() txtView.Text <- webClient.DownloadString("https://fivepm.azurewebsites.net/") )

استبدل fivepm.azurewebsites.net بعنوان URL لنشر JSON API الخاص بك. قم بتشغيل التطبيق وانقر فوق الزر الموجود في المحاكي. بعد قليل ، يجب أن ترى واجهة برمجة تطبيقات JSON تعود بنتيجة API الخاصة بك.

تحليل JSON

نحن على وشك الانتهاء! في الوقت الحالي ، يعرض تطبيقنا JSON الخام وهو غير قابل للقراءة إلى حد ما. الخطوة التالية ، إذن ، هي تحليل JSON وإخراج سلسلة أكثر قابلية للقراءة من قبل الإنسان. لتحليل JSON ، يمكننا استخدام مكتبة Newtonsoft.JSON من الخادم.

انتقل إلى مدير الحزم الخاص بك في NuGet وابحث عن Newtonsoft.JSON. قم بالتثبيت والعودة إلى ملف MainActivity.fs. قم باستيراده عن طريق إضافة "فتح Newtonsoft.Json".

أضف الآن نوع TZInfo إلى المشروع. يمكننا إعادة استخدام TZInfo من الخادم ، ولكن نظرًا لأننا في الواقع نحتاج فقط إلى حقلين ، يمكننا تحديد نوع مخصص هنا:

 type TZInfo = { tzName:string localTime: string }

أضف تعريف النوع فوق الوظيفة الرئيسية ، وقم الآن بتغيير الوظيفة الرئيسية على النحو التالي:

 button.Click.Add (fun args -> let webClient = new WebClient() let tzi = JsonConvert.DeserializeObject<TZInfo>(webClient.DownloadString("https://fivepm.azurewebsites.net/")) txtView.Text <- sprintf "It's (about) 5PM in the\n\n%s Timezone! \n\nSpecifically, it is %s there" tzi.tzName tzi.localTime )

الآن يتم إلغاء تسلسل نتيجة JSON API في كائن TZInfo واستخدامها لبناء سلسلة. قم بتشغيل التطبيق وانقر فوق الزر. يجب أن ترى السلسلة المنسقة تظهر على الشاشة.

في حين أن هذا التطبيق بسيط للغاية وربما غير مكرر ، فقد أنشأنا تطبيقًا للهاتف المحمول يستهلك واجهة برمجة تطبيقات F # JSON ، ويحول البيانات ويعرضها للمستخدم. وفعلنا كل ذلك في F #. لا تتردد في اللعب مع عناصر التحكم المختلفة ومعرفة ما إذا كان يمكنك تحسين التصميم.

ويوجد لدينا ذلك! تطبيق بسيط للهاتف المحمول F # وواجهة برمجة تطبيقات F # JSON ويخبر المستخدم بمكان الساعة الخامسة.

تغليف

لقد مررنا اليوم من خلال إنشاء واجهة برمجة تطبيقات ويب بسيطة وتطبيق Android بسيط باستخدام F # فقط ، مما يدل على كل من تعبير لغة F # وقوة نظام F # البيئي. ومع ذلك ، فإننا بالكاد خدشنا سطح تطوير F # ، لذلك سأكتب بضع مشاركات أخرى للبناء على ما ناقشناه اليوم. بالإضافة إلى ذلك ، آمل أن يكون هذا المنشور قد ألهمك لإنشاء تطبيقات F # خاصة بك!

يمكنك العثور على الكود الذي استخدمناه لهذا البرنامج التعليمي على GitHub.