মনো-ট্র্যাভারেবল থেকে "কনক্যাটম্যাপ" কীভাবে সাধারণ যুক্তিটি "টান" সক্ষম করতে পারে?


9

আমি হাস্কেল শিখছি এবং ইয়েসডের জন্য একটি সাধারণ ডিবি-বীজ প্রোগ্রাম করছিলাম যখন আমি এই আচরণে হোঁচট খেয়েছি যা বুঝতে আমার অসুবিধা হয়:

testFn :: Int -> Bool -> [Int]
testFn a b = if b then replicate 10 a else []

ইয়াসোদ জিএইচসিআই অধিবেশন:

$ :t concatMap testFn [3]
concatMap testFn [3] :: Bool -> [Int]
$ (concatMap testFn [1,2,3]) True
[1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3]

একরকম প্রতিটি ম্যাপিং থেকে একক ত্রি যুক্তিতে "দ্বিতীয় "টিকে" টানতে "সক্ষম হয়েছিল।

স্ট্যান্ডার্ড বেস প্রিলেড জিএইচসিআই অধিবেশন এমনকি এই প্রকাশটি সংকলন করতে অস্বীকার করেছে:

$ :t concatMap testFn [3]
error:
     Couldn't match type 'Bool -> [Int]' with '[b]'
      Expected type: Int -> [b]
        Actual type: Int -> Bool -> [Int]
     Probable cause: 'testFn' is applied to too few arguments
      In the first argument of 'concatMap', namely 'testFn'
      In the expression: concatMap testFn [3]

দেখা যাচ্ছে যে ইয়াসোদ মনো-ট্র্যাজেবল লাইব্রেরি ব্যবহার করেছে যার নিজস্ব রয়েছে concatMap:

$ :t concatMap
concatMap
  :: (MonoFoldable mono, Monoid m) =>
     (Element mono -> m) -> mono -> m

হাস্কেল বোঝার আমার বর্তমান স্তরে আমি বুঝতে পারি না যে এখানে কীভাবে প্রকারগুলি বিতরণ করা হয়। কেউ আমাকে ব্যাখ্যা করতে পারে (যতটা সম্ভব প্রাথমিক দিকনির্দেশিত) কীভাবে এই কৌশলটি করা হয়? testFnউপরের কোন অংশটি Element monoটাইপ করে চলেছে ?

উত্তর:


6

আমরা জানি কিছু প্রকারের তালিকা দিয়ে শুরু করি। (আমরা ভান করি যে সংখ্যাগুলি Intসরলতার জন্য - এটি আসলে প্রাসঙ্গিক নয়))

testFn :: Int -> Bool -> [Int]
[1,2,3] :: [Int]
True :: Bool

(concatMap testFn [1,2,3]) Trueএকইরূপে concatMap testFn [1,2,3] True, সুতরাং concatMapসেই সমস্ত আর্গুমেন্টের সাথে এক ধরণের মিল থাকতে হবে:

concatMap :: (Int -> Bool -> [Int]) -> [Int] -> Bool -> ???

???ফলাফলের ধরণ কোথায় মনে রাখবেন, সাহিত্যিকতার নিয়মের ->কারণে ডানদিকে সহযোগী হয়, সুতরাং উপরের টাইপিংটি একই রকম:

concatMap :: (Int -> (Bool -> [Int])) -> [Int] -> (Bool -> ???)

এর উপরে একটি সাধারণ টাইপ লিখুন। আমি মিলটি চিহ্নিত করতে কয়েকটি স্পেস যুক্ত করছি।

concatMap :: (MonoFoldable mono, Monoid m) =>
             (Element mono -> m              ) -> mono  -> m
concatMap :: (Int          -> (Bool -> [Int])) -> [Int] -> (Bool -> ???)

আহ হা! যদি আমরা নির্বাচন আমরা কোন মিল থাকতে পারে mযেমন Bool -> [Int], এবং monoযেমন [Int]। যদি আমরা এটি করি, তবে আমরা সীমাবদ্ধতাগুলি পূরণ করি MonoFoldable mono, Monoid m(নীচে দেখুন), এবং আমাদের কাছেও রয়েছে Element mono ~ Int, তাই সবকিছু পরীক্ষা করে দেখুন।

আমরা অনুমান যে ???হয় [Int]সংজ্ঞা থেকে m

বাধা সম্পর্কে: কারণ MonoFoldable [Int], বলার অপেক্ষা রাখে না। [Int]একটি Intএলিমেন্ট টাইপের সাথে স্পষ্টভাবে একটি লিস্টের মতো টাইপ এবং এটি এটির MonaFoldableসাথে এটি তৈরি করার পক্ষে যথেষ্ট ।IntElement

কারণ Monoid (Bool -> [Int])এটি কিছুটা জটিল। আমাদের কাছে যে কোনও ফাংশনের ধরণ A -> Bযদি মোনোয়েড হয় তবে Bতা একটি মনোয়েড। এটি বিন্দুমুখী ফ্যাশনে ক্রিয়াকলাপ সম্পাদন করে অনুসরণ করে। আমাদের সুনির্দিষ্ট ক্ষেত্রে, আমরা [Int]মনোয়েড হওয়ার উপর নির্ভর করি এবং আমরা পাই:

mempty :: Bool -> [Int]
mempty = \_ -> []

(<>) :: (Bool -> [Int]) -> (Bool -> [Int]) -> (Bool -> [Int])
f <> g = \b -> f b ++ g b

1
দুর্দান্ত ব্যাখ্যা! আপনি যেভাবে ব্যাখ্যা করেছেন এবং প্রকারের প্রান্তিককরণ করেছেন ঠিক তেমনই আমি দেখতে চেয়েছিলাম, ধন্যবাদ!
ডিমসুজ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.