আমি মোট এবং মার্জিত উপায়ে একটি স্থির-সর্বনিম্ন দৈর্ঘ্যের তালিকাটি কীভাবে ব্যবহার করতে পারি?


10

আমি বর্তমানে এমন একটি ফাংশন নিয়ে কাজ করছি যা এভাবে চলে:

foo = (\(a:b:c:d:e:f:_) -> foobar a b c d e f) . (++ repeat def)

অন্য কথায়, একটি তালিকা দেওয়া হয়েছে, এটি কোনও কিছুর জন্য প্রথম ছয় উপাদান ব্যবহার করে এবং যদি তালিকাটি ছয়টি উপাদানের চেয়ে কম দীর্ঘ হয় তবে defএটি নিখোঁজদের জন্য স্ট্যান্ড-ইন হিসাবে ব্যবহার করে। এটি মোট, তবে এর টুকরাগুলি (ঠিক যেমন map fromJust . filter isJust) নয়, তাই এটি আমার পছন্দ হয় না। আমি এটি পুনরায় লেখার চেষ্টা করেছি যাতে এটি কোনও পক্ষপাতিত্ব ব্যবহার করার প্রয়োজন না হয় এবং এটি পেয়ে যায়:

foo [] = foobar def def def def def def
foo [a] = foobar a def def def def def
foo [a,b] = foobar a b def def def def
foo [a,b,c] = foobar a b c def def def
foo [a,b,c,d] = foobar a b c d def def
foo [a,b,c,d,e] = foobar a b c d e def
foo (a:b:c:d:e:f:_) = foobar a b c d e f

আমি প্রযুক্তিগতভাবে যা চাই তা করেছি, তবে এখন এটি একটি বিশাল জগাখিচুড়ি। কীভাবে আমি এটি আরও মার্জিত এবং কম পুনরাবৃত্তিজনক উপায়ে করতে পারি?


2
হতে পারে, একটি uncons :: Default a => [a] -> (a,[a])ডিফল্ট লিখুন def। বা একটি ডিফল্ট takeWithDef। এবং / অথবা একটি দর্শন প্যাটার্ন / প্যাটার্ন প্রতিশব্দ। যদিও এর জন্য কিছু সহায়ক সহায়ক কোড লেখার প্রয়োজন।
চি

@ কচি আমি মনে করি এটাই আমি নিয়ে যাব। আপনি যদি এটির উত্তর দেন তবে আমি তা গ্রহণ করব।
জোসেফ সিবিল-রিইনস্টেট মনিকা

2
এটির জন্য মূল্যবান, আমি মনে করি এর সামগ্রিকতা যুক্তি case xs ++ repeat def of a:b:c:d:e:f:_ -> ...যথেষ্ট স্থানীয় যে আমি কেবল এটি ব্যবহার এবং বিদ্যমান উত্তরগুলি প্রবর্তন করছে এমন সমস্ত অতিরিক্ত যন্ত্রপাতি এড়িয়ে যাওয়া সম্পর্কে দু'বার চিন্তা করব না। এটি সাধারণত আরও বিশ্বব্যাপী সামগ্রিকতা যুক্তি (যাতে একাধিক ফাংশন কল জুড়ে রক্ষাকারী জড়িত থাকে) যেমন আমাকে ঘাবড়ে যায়।
ড্যানিয়েল ওয়াগনার

প্রকৃতপক্ষে takeWithDefএটি যদি কোনও নিয়মিত তালিকা ফেরত দেয় তবে তা ব্যবহারযোগ্য নয়, যেহেতু আমাদের সেই ধরণের মিলের প্রয়োজন: - / ড্যানিয়েল তার দ্বিতীয় উত্তরে নীচে যা লিখেছিলেন তার যথাযথ সমাধান। unconsশুধুমাত্র প্রথম উপাদানটি পায় তাই এটি কার্যকর নয়।
চি

উত্তর:



6

এটি কমপক্ষে সংক্ষিপ্ত:

foo (a:b:c:d:e:f:_) = foobar a b c d e f
foo xs = foo (xs ++ repeat def)

আপনি সহজেই দেখতে পারেন যে নিদর্শনগুলি সম্পূর্ণরূপে কার্যকর, তবে এখন এটি সর্বদা বন্ধ হয়ে যায় তা দেখতে আপনাকে কিছুটা ভাবতে হবে। সুতরাং আপনি এটিকে উন্নতি হিসাবে বিবেচনা করতে পারেন কিনা তা আমি জানি না।

অন্যথায় আমরা এটি রাজ্য মনডের সাথে করতে পারি, যদিও এটি কিছুটা ভারী ওজনের:

foo = evalState (foobar <$> pop <*> pop <*> pop <*> pop <*> pop <*> pop)
  where
    pop = do xs <- get
             case xs of [] -> pure def
                        y:ys -> put ys >> pure y

আমি অসীম স্ট্রিম প্রকারের মতো ব্যবহার করে কল্পনাও করতে পারি

data S a = S a (S a)

কারণ তারপর আপনি গঠন করা যেতে পারে fooএর বাইরে repeat :: a -> S a, prepend :: [a] -> S a -> S aএবং take6 :: S a -> (a,a,a,a,a,a), সব যা মোট হতে পারে। আপনার যদি ইতিমধ্যে এই জাতীয় কোনও সুবিধা না থাকে তবে সম্ভবত এটি মূল্যবান নয়।


3
ওহ, আমি স্ট্রিম ধারণাটি অনেক পছন্দ করি। ইনফিক্স কনস্ট্রাক্টরের মতো data S a = a :- S a; infixr 5 :-দেখতে এটি বেশ পরিষ্কার দেখাচ্ছে; foo xs = case prepend xs (repeat def) of a:-b:-c:-d:-e:-f:-_ -> foobar a b c d e f
ড্যানিয়েল ওয়াগনার

4

কেবল মজাদার জন্য (এবং প্রস্তাবিত নয়, এটি মজাদার জন্য), এখানে আরও একটি উপায় রয়েছে:

import Data.Default

data Cons f a = a :- f a
infixr 5 :-

data Nil a = Nil -- or use Proxy

class TakeDef f where takeDef :: Default a => [a] -> f a
instance TakeDef Nil where takeDef _ = Nil
instance TakeDef f => TakeDef (Cons f) where
    takeDef (x:xs) = x :- takeDef xs
    takeDef xs = def :- takeDef xs

foo xs = case takeDef xs of
    a:-b:-c:-d:-e:-f:-Nil -> foobar a b c d e f

প্যাটার্ন ম্যাচটিতে আপনি যে ধরণের ব্যবহার করেন takeDefতা কতগুলি উপাদানকে দেখতে হবে তা বলার মতো টাইপ-লেভেল স্বাভাবিক passing


1
এটি এখন পর্যন্ত আমার পছন্দের পদ্ধতির। আমি সম্ভবত এটি পরিপূরক একটি ভিউ প্যাটার্ন ব্যবহার করব। (কেন "প্রস্তাবিত নয়"? কনসগুলি কী?)
চি

3
এটি টাইপ-লেভেল প্রোগ্রামিংয়ে আপনি যখন প্রচুর পরিমাণে বিনিয়োগ করেন তখন ঠিক কী ভুল হতে শুরু করে তা সূচিত করে: এক-লাইন কী ছিল, তাত্ক্ষণিকভাবে বোধগম্য প্রোগ্রামের বেলুনগুলি দশটি লাইনের মধ্যে বেরিয়েছে যার জন্য পাঠককে তাদের মানসিক টাইপ-ইনফারেন্স ইঞ্জিনকে গুরুতরভাবে নিযুক্ত করতে হবে।
ড্যানিয়েল ওয়াগনার

1
আমি আপনার পয়েন্ট দেখুন. আমি foo (takeDef -> a:-b:-c:-d:-e:-f:-Nil) -> foobar a b c d e fএক লাইন হিসাবে গণনা । আমি বাকীটি গণনা করি না কারণ এটি কোড যা কোনও লাইব্রেরিতে থাকা উচিত, পুনরায় ব্যবহারের জন্য। যদি কেবল এই মামলার জন্য এটি লিখতে হয় তবে আপনি যেমন বলছেন তেমন স্পষ্টভাবে ওভারকিল।
চি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.