রেকর্ডে একটি একক ক্ষেত্র বরাদ্দ করার জন্য শর্টহ্যান্ড উপায়, বাকি ক্ষেত্রগুলি অনুলিপি করার সময়?


119

ধরা যাক আমার কাছে নিম্নলিখিত রেকর্ড এডিটি রয়েছে:

data Foo = Bar { a :: Integer, b :: String, c :: String }

আমি এমন একটি ফাংশন চাই যা একটি রেকর্ড গ্রহণ করে এবং একটি রেকর্ড (একই ধরণের) ফেরত দেয় যেখানে ক্ষেত্রগুলির মধ্যে একটি ছাড়া সমস্ত ক্ষেত্রে আর্গুমেন্ট হিসাবে পাসের সাথে একই মান রয়েছে:

walkDuck x = Bar { a = a x, b = b x, c = lemonadeStand (a x) (b x) }

উপরের কাজগুলি, তবে আরও ক্ষেত্রগুলির সাথে একটি রেকর্ডের জন্য (বলুন 10), এই জাতীয় ফাংশন তৈরি করা অনেকগুলি টাইপিংয়ের প্রয়োজন যা আমি মনে করি এটি যথেষ্ট অপ্রয়োজনীয়।

একই কাজ করার কি কোনও ক্লান্তিকর উপায় আছে?


3
আপডেট করার জন্য রেকর্ড সিনট্যাক্স বিদ্যমান, তবে দ্রুত জটিল হয়ে ওঠে। পরিবর্তে লেন্স একবার দেখুন ।
ক্যাট প্লাস প্লাস

উত্তর:


155

হ্যাঁ, রেকর্ড ক্ষেত্রগুলি আপডেট করার একটি দুর্দান্ত উপায় রয়েছে। GHCi এ আপনি করতে পারেন -

> data Foo = Foo { a :: Int, b :: Int, c :: String }  -- define a Foo
> let foo = Foo { a = 1, b = 2, c = "Hello" }         -- create a Foo
> let updateFoo x = x { c = "Goodbye" }               -- function to update Foos
> updateFoo foo                                       -- update the Foo
Foo {a = 1, b = 2, c = "Goodbye" }

9
RecordWildCardsএক্সটেনশান হিসাবে ভাল চমৎকার, একটি সুযোগ "আনপ্যাক" ক্ষেত্র হতে পারে। আপডেটের জন্য এটি যদিও ততটা দুর্দান্ত নয়:incrementA x@Foo{..} = x { a = succ a }
জোন পুরি

2
বিটিডাব্লু, ফ্রেজে (জেভিএমের জন্য একটি হাস্কেল) আপনি ফাংশনটি সংজ্ঞায়িত করবেন updateFoo x = x.{ c = "Goodbye" }( .অপারেটরকে নোট করুন )।
ডিবি


ধন্যবাদ। দুঃখজনকভাবে অনেক সময় হয়ে গেছে যেহেতু আমি কোনও হাস্কেল লিখেছি!
ক্রিস টেলর

37

লেন্সগুলির জন্য এটি একটি ভাল কাজ :

data Foo = Foo { a :: Int, b :: Int , c :: String }

test = Foo 1 2 "Hello"

তারপর:

setL c "Goodbye" test

আপনার স্ট্রিংয়ে 'পরীক্ষার' ফিল্ড 'সি' আপডেট করবে।


5
এবং লেন্সের মতো প্যাকেজগুলি প্রায়শই ক্ষেত্রগুলি পাওয়ার ও সেট করার জন্য ফাংশনগুলির পাশাপাশি অপারেটরগুলির সংজ্ঞা দেয়। উদাহরণস্বরূপ, test $ c .~ "Goodbye"এটি কিভাবে lensiirc করবেন। আমি বলছি না এটি স্বজ্ঞাত, তবে একবার আপনি অপারেটরদের জানলে আমি আশা করি এটি সহজেই আসবে $
থমাস এম ডুবুইসন

3
আপনি কি জানেন সেটেল কোথায় গেছে? আমি আমদানির করছি Control.Lens কিন্তু ghc প্রতিবেদন করা হচ্ছে যে setL undefined করা হয়।
dbanas

1
সেটএল এর পরিবর্তে সেট ব্যবহার করুন
সুবহাদ আমি

16

আপনাকে সহায়ক ফাংশনগুলি সংজ্ঞায়িত করতে বা লেন্স নিয়োগ করার দরকার নেই। স্ট্যান্ডার্ড হাস্কেল আপনার যা প্রয়োজন ইতিমধ্যে তা পেয়েছে। আসুন ডন স্টুয়ার্টের উদাহরণটি ধরুন:

data Foo = Foo { a :: Int, b :: Int , c :: String }

test = Foo 1 2 "Hello"

তারপরে আপনি কেবল test { c = "Goodbye" }একটি আপডেট রেকর্ড পেতে বলতে পারেন।

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