سؤال

لقد كنت أحاول الدخول إلى F# بشكل متقطع لفترة من الوقت ولكني أواصل التأجيل.لماذا؟

لأنه بغض النظر عن مورد "المبتدئين" الذي أحاول إلقاء نظرة عليه، فإنني أرى أمثلة بسيطة جدًا تبدأ باستخدام عامل التشغيل ->.

ومع ذلك، لم أجد حتى الآن في أي مكان ما يقدم شرحًا واضحًا وبسيطًا لما يعنيه هذا العامل.يبدو الأمر كما لو أنه يجب أن يكون واضحًا جدًا لدرجة أنه لا يحتاج إلى شرح حتى للمبتدئين.

لذلك يجب أن أكون كثيفًا حقًا أو ربما ما يقرب من 3 عقود من الخبرة السابقة تعيقني.

هل يمكن لأي شخص أن يشرح ذلك أو يشير إلى مصدر يسهل الوصول إليه بالفعل ويشرحه؟

هل كانت مفيدة؟

المحلول

'->' ليس عامل تشغيل.يظهر في بناء جملة F# في عدد من الأماكن، ويعتمد معناه على كيفية استخدامه كجزء من بنية أكبر.

داخل النوع، يصف "->" أنواع الوظائف كما وصفها الأشخاص أعلاه.على سبيل المثال

let f : int -> int = ...

يقول أن "f" هي دالة تأخذ int وترجع int.

داخل لامدا ("الشيء الذي يبدأ بالكلمة الرئيسية "مرح")، '->' هو بناء الجملة الذي يفصل الوسيطات عن الجسم.على سبيل المثال

fun x y -> x + y + 1

هو تعبير يحدد دالة وسيطتين مع التنفيذ المحدد.

داخل بنية "المطابقة"، يكون "->" عبارة عن بناء جملة يفصل الأنماط عن التعليمات البرمجية التي يجب تشغيلها في حالة مطابقة النمط.على سبيل المثال، في

match someList with
| [] -> 0
| h::t -> 1

العناصر الموجودة على يسار كل "->" هي أنماط، والأشياء الموجودة على اليمين هي ما يحدث إذا تمت مطابقة النمط الموجود على اليسار.

قد تكون جذور صعوبة الفهم ناجمة عن الافتراض الخاطئ بأن '->' هو "عامل" له معنى واحد.قد يكون القياس "." في C#، إذا لم تر أي رمز من قبل ، وحاول تحليل "." يقوم المشغل بناءً على النظر إلى "OBJ.Method" و "3.14" و "System.Crollections" ، قد تشعر بالارتباك الشديد ، لأن الرمز له معاني مختلفة في سياقات مختلفة.وبمجرد أن تعرف ما يكفي من اللغة للتعرف على هذه السياقات، تصبح الأمور واضحة.

نصائح أخرى

ويعني في الأساس "خرائط ل".اقرأها بهذه الطريقة أو "تتحول إلى" أو شيء من هذا القبيل.

إذن، من F# في 20 دقيقة درس تعليمي،

> List.map (fun x -> x % 2 = 0) [1 .. 10];;
val it : bool list
= [false; true; false; true; false; true; false; true; false; true]

يعرّف الرمز (المرح i -> i ٪ 2 = 0) وظيفة مجهولة ، تسمى تعبير Lambda ، والتي تحتوي على معلمة x وتُرجع الوظيفة نتيجة "x ٪ 2 = 0" ، وهو ما إذا كان x هو حتى.

السؤال الأول - هل أنت على دراية بتعبيرات لامدا في لغة C#؟إذا كان الأمر كذلك، فإن -> في F# هو نفس => في C# (أعتقد أنك قرأته "يذهب إلى").

يمكن أيضًا العثور على عامل التشغيل -> في سياق مطابقة الأنماط

match x with
| 1 -> dosomething
| _ -> dosomethingelse

لست متأكدًا مما إذا كان هذا أيضًا تعبير لامدا، أو أي شيء آخر، ولكن أعتقد أن عبارة "يذهب إلى" لا تزال سارية.

ربما ما تشير إليه حقًا هو الاستجابات "المبهمة" للمحلل اللغوي F#:

> let add a b = a + b
val add: int -> int -> int

هذا يعني (كما توضح معظم الأمثلة) أن الإضافة عبارة عن "val" يأخذ عددين من ints ويعيد int.بالنسبة لي كان هذا مبهمًا تمامًا في البداية.أعني، كيف أعرف أن الإضافة ليست قيمة تأخذ int واحد وترجع اثنين ints؟

حسنًا، الأمر هو أن الأمر كذلك إلى حدٍ ما.إذا قمت بإضافة int واحد فقط، فسأستعيد (int -> int):

> let inc = add 1
val inc: int -> int

هذا (الكاري) هو أحد الأشياء التي تجعل F # مثيرة جدًا بالنسبة لي.

للحصول على معلومات مفيدة حول F#، وجدت أن المدونات أكثر فائدة بكثير من أي من "الوثائق" الرسمية:فيما يلي بعض الأسماء للتحقق منها

(أ -> ب) تعني "الوظيفة من أ إلى ب".في التعليق التوضيحي للنوع، يشير إلى نوع الوظيفة.على سبيل المثال، ف :(int -> String) يعني أن f يشير إلى دالة تأخذ عددًا صحيحًا وترجع سلسلة.كما يتم استخدامه كمنشئ لهذه القيم، كما في

val f : (int -> int) = fun n -> n * 2

الذي ينشئ قيمة هي دالة من رقم ما n إلى نفس الرقم مضروبًا في اثنين.

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

' -> ' تعني الوظيفة.

'a -> 'b هي دالة تأخذ "a" وترجع "b".

('a * 'b) -> ('c * 'd) هي دالة تأخذ صفًا من النوع ('a, 'b) وتُرجع صفًا من ('c, 'd).مثل int/string تُرجع float/char.

يصبح الأمر مثيرًا للاهتمام في الحالة المتتالية لـ 'a -> 'b -> 'c.هذه دالة تأخذ 'a وترجع دالة ('b -> 'c)، أو دالة تأخذ 'b -> 'c.

لذلك إذا كتبت:دع f x y z = ()

سيكون النوع f :'a -> 'b -> 'c -> وحدة، لذا إذا قمت بتطبيق المعلمة الأولى فقط، فستكون النتيجة دالة متجانسة 'b -> 'c -> 'unit.

من مايكروسوفت:

أنواع الوظائف هي الأنواع المعطاة لقيم دالة من الدرجة الأولى ويتم كتابتها int -> int.فهي تشبه أنواع المندوبين .NET ، باستثناء أنها لا تمنح أسماء.يمكن استخدام جميع معرفات وظائف F# كقيم دالة من الدرجة الأولى ، ويمكن إنشاء قيم الوظائف المجهولة باستخدام (المرح ...-> ...) صيغة التعبير.

العديد من الإجابات الرائعة على هذه الأسئلة، شكرا للناس.أود أن أضع هنا إجابة قابلة للتحرير تجمع الأشياء معًا.

بالنسبة لأولئك الذين هم على دراية بفهم C# -> أن يكون نفس تعبير => لامبا يعد خطوة أولى جيدة.هذا الاستخدام هو :-

fun x y -> x + y + 1

يمكن أن يفهم على أنه يعادل: -

(x, y) => x + y + 1;

ومع ذلك، فمن الواضح أن -> له معنى أكثر جوهرية ينبع من مفهوم أن الوظيفة التي تأخذ معلمتين مثل ما ورد أعلاه يمكن اختزالها (هل هذا هو المصطلح الصحيح؟) إلى سلسلة من الوظائف التي تأخذ معلمة واحدة فقط.

ومن ثم عندما يتم وصف ما سبق على النحو التالي: -

Int -> Int -> Int

لقد ساعدنا حقًا في معرفة أن -> هو الترابط الصحيح وبالتالي يمكن اعتبار ما سبق: -

Int -> (Int -> Int)

آها!لدينا دالة تأخذ Int وترجع (Int -> Int) (وظيفة مكررة؟).

وقد ساعد أيضًا الشرح الذي -> يمكن أن يظهر أيضًا كجزء من تعريف النوع.(Int -> Int) هو نوع أي دالة تأخذ Int وترجع Int.

من المفيد أيضًا أن يظهر -> في بناء جملة آخر مثل المطابقة ولكن ليس له نفس المعنى؟هل هذا صحيح؟لست متأكدا من ذلك.أظن أن لها نفس المعنى ولكن ليس لدي المفردات للتعبير عن ذلك بعد.

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

في سياق تعريف الوظيفة، فهي مشابهة لـ => من تعبير لامدا في C# 3.0.

F#: let f = fun x -> x*x
C#: Func<int, int> f = x => x * x;

ال -> في F# يُستخدم أيضًا في مطابقة الأنماط، حيث يعني:إذا كان التعبير يطابق الجزء الموجود بين | و ->, ، ثم ما بعد ذلك -> يجب أن تعاد نتيجة لذلك:

let isOne x = match x with
 | 1 -> true
 | _ -> false

الشيء الجميل في لغات مثل Haskell (وهي مشابهة جدًا للغة F#، لكنني لا أعرف الصيغة الدقيقة - من المفترض أن يساعدك هذا على الفهم ->، بالرغم من ذلك) هو أنه يمكنك تطبيق أجزاء فقط من الوسيطة لإنشاء بالكاري المهام:

adder n x y = n + x + y

بعبارة أخرى:"أعطني ثلاثة أشياء، وسأجمعها معًا".عندما ترمي أرقامًا عليها، سيستنتج المترجم أنواع n x وy.قل أنك تكتب

adder 1 2 3

نوع 1 و 2 و 3 هو Int.لذلك:

adder :: Int -> Int -> Int -> Int

أي أعطني ثلاثة أعداد صحيحة، وسأصبح عدداً صحيحاً في النهاية، أو مثل قولك:

five :: Int
five = 5

ولكن، هنا الجزء الجميل!جرب هذا:

add5 = adder 5

كما تتذكر، يأخذ Adder int، int، int، ويعطيك int مرة أخرى.لكن هذه ليست الحقيقة كاملة، كما سترون قريبا.في الواقع، add5 سيكون له هذا النوع:

add5 :: Int -> Int -> Int

سيكون الأمر كما لو أنك "قمت بتقشير" الأعداد الصحيحة (أقصى اليسار)، ولصقتها مباشرةً على الدالة.وبالنظر عن كثب إلى توقيع الدالة، نلاحظ أن -> ترتبط باليمين، أي:

addder :: Int -> (Int -> (Int -> Int))

وهذا يجب أن يوضح تمامًا:عندما تعطي الجامع العدد الصحيح الأول، فسيتم تقييمه إلى ما هو موجود على يمين السهم الأول، أو:

add5andtwomore :: Int -> (Int -> Int)
add5andtwomore = adder 5

يمكنك الآن استخدام add5andtwomore بدلاً من "adder 5".بهذه الطريقة، يمكنك تطبيق عدد صحيح آخر للحصول على (على سبيل المثال) "add5and7andonemore":

add5and7andonemore :: Int -> Int
add5and7andonemore = adder 5 7

كما ترى، فإن add5and7andonemore يريد وسيطة أخرى تمامًا، وعندما تعطيها واحدة، ستصبح فجأة عددًا صحيحًا!

  > add5and7andonemore 9
 => ((add5andtwomore) 7) 9
 => ((adder 5) 7) 9)
<=> adder 5 7 9

باستبدال المعلمات إلى جامع (n x y) لـ (5 7 9) نحصل على:

  > adder 5 7 9 = 5 + 7 + 9
 => 5 + 7 + 9
 => 21

في الحقيقة, ، plus هي أيضًا مجرد وظيفة تأخذ int وتعطيك int آخر، لذا فإن ما ورد أعلاه يشبه إلى حد كبير:

  > 5 + 7 + 9
 => (+ 5 (+ 7 9))
 => (+ 5 16)
 => 21

ها أنت ذا!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top