سؤال

جلب الشخص في Reddit هذا الرمز إلى انتباهي:

main = do
  let ns = [print 1, print 2, print 3]
  sequence_ ns
  sequence_ $ reverse ns
  sequence_ $ tail ns ++ [head ns]
  head ns

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

مدهش.

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

ns !! 0

واحصل على شيء مثل [Print، 1] ثم قم بتغيير العنصر الأخير، ويقول، 3.14 بحيث تتم طباعة الوظيفة 3.14.

هل من الممكن على الإطلاق في Haskell أو يجب أن أعود للتو إلى Lisp؟

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

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

المحلول

إنه أكثر تعقيدا قليلا مما كانت عليه في LISP، ولكن بالنسبة للمتصارج في Haskell، يمكنك استخدامه قالب haskell..

على سبيل المثال، [|print 1|] سوف ترجم إلى

return $ AppE (VarE $ mkName "print") (LitE $ IntegerL 1)

التي لديها النوع Q Exp (اقتباس تعبير).

إذا كنت ترغب في تقليص البيانات الخاصة بك في اقتباس، [|print $(foo 3.14)|] سوف تنفذ foo 3.14 في تجميع الوقت.

نصائح أخرى

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

data App a b = App (a -> b) a
runApp (App a b) = a b
ns = [App print 1, App print 2, App print 3]
main = do
    sequence_ $ map runApp ns
    let ns2 = [App fun (arg^2) | App fun arg <- ns]
    sequence_ $ map runApp ns2

المخرجات

1
2
3
1
4
9

تريد تحريغ القائمة؟ يجب أن تعود إلى LISP ؛-)

القيم غير ثابتة في haskell. Haskell-Way هو إنشاء قائمة جديدة تعادل القائمة القديمة باستثناء العنصر الأخير.

(هناك بعض الحيل التي تنطوي على monads حيث يمكنك محاكاة القيم والمؤشرات المتغيرة، ولكن ربما لا تكون ما تريد هنا.)

تحرير: غير متأكد تماما من أنني أفهم السؤال المحرر، ولكن يمكنك التعامل مع الوظيفة والوسيطة بشكل منفصل كبيانات ثم "تطبيق" لاحقا، على سبيل المثال؛

do
    let ns = [(print, 1), (print, 2), (print, 3)]
    sequence_ $ map (\(f,a)->f a) ns

كما تم القول أن طريقة Haskell هي مجرد إنشاء قائمة جديدة، ولكن يمكنك الحصول على صفائف متغيرة داخل IO Monad مع Ioarray إذا كنت تريد حقا

import Data.Array.IO

seqArr_ arr = getElems arr>>=sequence_

main= do
  arr <- newListArray (0,2) [print 1,print 2,print 3] :: IO (IOArray Int (IO ()))
  seqArr_ arr  -- prints 1 2 3
  writeArray arr 2 (print 3.14) -- change the last element
  seqArr_ arr  -- prints 1 2 3.14
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top