হাসকেলে গল্ফ করার টিপস


73

হাসকেলে গল্ফ করার জন্য আপনার কাছে কোন সাধারণ টিপস রয়েছে? আমি এমন ধারণাগুলি সন্ধান করছি যা কোড গল্ফ সমস্যাগুলিতে প্রয়োগ করা যেতে পারে যা হাস্কেলের সাথে অন্তত কিছুটা নির্দিষ্ট। অনুগ্রহ করে প্রতি উত্তরে মাত্র একটি টিপ পোস্ট করুন।


আপনি যদি হাসকেলে গল্ফিংয়ের ক্ষেত্রে নতুন হন তবে দয়া করে হাসকেলে গল্ফিংয়ের নিয়মাবলী সম্পর্কিত গাইড দেখুন । এছাড়াও একটি ডেডিকেটেড হাস্কেল চ্যাট রুম: অফ মোনডস এবং মেন


1
এখনও অবধি উত্তরগুলি দেখে, আমি সন্দেহ করছি যে হাসকল কোড গল্ফিংয়ের জন্য এমনকি একটি ভাল ভাষা কিনা?
অনিমেষ 'কোডার'

10
প্রতি উত্তরে কেন একটি টিপস? এছাড়াও, প্রতিটি ভাষা গল্ফ করার জন্য একটি ভাল ভাষা। সবসময় জয়ের আশা করবেন না।
কাকামেট

6
@ আঙ্কেলমেট এইভাবে লোকেরা খারাপ লোককে উজ্জীবিত না করে ভালকে শীর্ষে উন্নীত করতে পারে কেবল কারণ তারা একই উত্তরে একই লোক লিখেছিল।
মাস্টারমাস্টিক

3
বিশেষ অনুরোধ, স্ট্রিং সংক্ষেপণ।
জে আতকিন

এটি সম্ভবত অ্যাঞ্জর হিসাবে উপযুক্ত নয় তবে আমি এটি এখানে এখানে যুক্ত করতে চাই: উইকি.হসেলেল.আর
প্রাইম

উত্তর:


45

বাইনারি ফাংশনগুলির পরিবর্তে ইনফিক্স অপারেটরগুলি সংজ্ঞায়িত করুন

এটি সংজ্ঞা বা কল অনুযায়ী সাধারণত এক বা দুটি স্পেস সংরক্ষণ করে।

0!(y:_)=y
x!(y:z)=(x-1)!z

বনাম

f 0(y:_)=y
f x(y:z)=f(x-1)z

1 বাইট অপারেটার জন্য উপলব্ধ প্রতীক !, #, %, &, এবং ?। অন্যান্য সমস্ত এএসসিআইআই বিরামচিহ্ন হয় ইতোমধ্যে প্রিলেড (যেমন $) দ্বারা অপারেটর হিসাবে সংজ্ঞায়িত হয়েছে বা হাস্কেলের সিনট্যাক্সে (যেমন @) এর একটি বিশেষ অর্থ রয়েছে ।

আপনার যদি পাঁচটির বেশি অপারেটরের প্রয়োজন হয় তবে আপনি উপরের সংমিশ্রণগুলি ব্যবহার করতে পারেন, যেমন !#কিছু ইউনিকোড বিরামচিহ্নগুলি যেমন (ইউটিএফ -8 এ সমস্ত 2 বাইট):

¡ ¢ £ ¤ ¥ ¦ § ¨ © ¬ ® ¯ ° ± ´ ¶ · ¸ ¿ × ÷

11
দ্রষ্টব্য: এটি তিন বা ততোধিক আর্গুমেন্ট সহ ফাংশনগুলির জন্যও ব্যবহার করা যেতে পারে। (x!y)z=x+y*zএবং (x#y)z u=x*z+y*uউভয়ই প্রত্যাশার মতো কাজ করে।
জাগারব

3
এটি ফাংশন আর্গুমেন্টগুলির জন্যও ব্যবহার করা যেতে পারে, যেমন\f g(!)x y->f g!x y\f g j x y->j(f g)(x y)
ইজারাং ফল

2
কখনও কখনও বাইনারি অপারেটরগুলিতে অ্যানারি ফাংশনগুলি পরিবর্তন করা উপকারী তবে যদি আপনি অন্যথায় বন্ধনী ব্যবহার করতে চান - এর g x=…;g(f x)চেয়ে দীর্ঘ হয়_?x=…;0!f x
Ang

29

যেখানে উপযুক্ত সেখানে অর্থহীন (বা -ফ্রি) স্বরলিপি ব্যবহার করুন

প্রায়শই এক বা দুটি পরামিতি সহ একটি ফাংশন বিন্দু মুক্ত লেখা যেতে পারে।

সুতরাং এমন উপাদানগুলির তালিকার একটি অনুসন্ধানের জন্য যাগুলির উপাদানগুলি অদলবদল করা হয়েছে তা নির্দ্বিধায় লেখা আছে:

revlookup :: Eq b => b -> [(a, b)] -> Maybe a
revlookup e l=lookup e(map swap l)

(এটি কী করছে তা বুঝতে আপনাকে সহায়তা করার জন্য প্রকারটি রয়েছে))

আমাদের উদ্দেশ্যে এটি আরও ভাল:

revlookup=(.map swap).lookup

28

তালিকা monad ব্যবহার করুন

একটি দ্রুত পর্যালোচনা:

xs >> ys        =  concat $ replicate (length xs) ys
xs >>= f        =  concatMap f xs
mapM id[a,b,c]  =  cartesian product of lists: a × b × c
mapM f[a,b,c]   =  cartesian product of lists: f a × f b × f c

উদাহরণ:

  • দুবার একটি তালিকা পুনরাবৃত্তি করা হচ্ছে

    Prelude> "aa">>[1..5]
    [1,2,3,4,5,1,2,3,4,5]
    
  • অপেক্ষাকৃত ছোট concatMap

    Prelude> reverse=<<["Abc","Defgh","Ijkl"]
    "cbAhgfeDlkjI"
    
  • সংক্ষিপ্ত concat+ তালিকা অনুধাবন

    Prelude> do x<-[1..5];[1..x]
    [1,1,2,1,2,3,1,2,3,4,1,2,3,4,5]
    
  • কার্টিজিয়ান পণ্য

    Prelude> mapM id["Hh","io",".!"]
    ["Hi.","Hi!","Ho.","Ho!","hi.","hi!","ho.","ho!"]
    
  • একটি জাল উপর স্থানাঙ্কের তালিকা

    Prelude> mapM(\x->[0..x])[3,2]
    [[0,0],[0,1],[0,2],[1,0],[1,1],[1,2],[2,0],[2,1],[2,2],[3,0],[3,1],[3,2]]
    

1
এর চেয়েও বেশি ব্যবহারের [0..b]>>[a]পরিবর্তে আমি দরকারী খুঁজে পেয়েছি replicate a b
গম উইজার্ড

3
@ ওয়েট উইজার্ড এর a<$[1..b]চেয়ে আরও খাটো replicate
লিন

=<<আপনাকে আমদানি করতে বাধ্য করে Control.Monad। অন্য কোনও কারণে যদি আপনার এটির প্রয়োজন না হয়, তর্কগুলি অদলবদল করা এবং ব্যবহার করা >>=আরও সংক্ষিপ্ত বলে মনে হয়।
dfeuer

OTOH, Data.Traversableযাইহোক আপনার যদি প্রয়োজন হয় তবে কার্টেসিয়ান পণ্যের উদাহরণটি ছোট করা যেতে পারে for["Hh","io",".!"]id
dfeuer

2
(=<<)প্রস্তাবনা রয়েছে , আসলে! আমি এটা অনেক ব্যবহার করেছি।
লিন

28

রক্ষীদের শর্তযুক্ত নয়:

f a=if a>0 then 3 else 7
g a|a>0=3|True=7

ইনডেন্ট নয় সেমিকোলন ব্যবহার করুন

f a=do
  this
  that
g a=do this;that

বুলিয়ান ফাংশনগুলির জন্য বুলিয়ান এক্সপ্রেশন ব্যবহার করুন

f a=if zzz then True else f yyy
g a=zzz||f yyy

(এসও আমাকে আলাদাভাবে এগুলি পোস্ট করতে দেওয়া সম্পর্কে বেদনা হচ্ছে)


2
এছাড়াও, &&তালিকা বোধের অভ্যন্তরে পরিবর্তে একাধিক প্রহরী ব্যবহার করুন ।
জন ডিভোরাক

ভাল একজন জান - আপনার উত্তর দেওয়া উচিত, আমি এটির জন্য ভোট দিয়ে যাব
বাজরঘ

5
প্রথম উদাহরণটি আরও True=> সংক্ষিপ্ত করা যেতে পারে1>0
জন ডিভোরাক

1
প্রথম উদাহরণে, আমি ধরে নিচ্ছি আপনার অর্থf a=if a>0 then 3 else 7
সাইওস

এমনকি এতে কোনও যুক্তি না থাকলে গার্ড কাজ করে।
আকাংকা

24

interact :: (String → String) → IO ()

লোকেরা প্রায়শই ভুলে যায় যে এই ফাংশনটি বিদ্যমান - এটি সমস্ত স্টিডিনকে ধরে এবং এটি একটি (খাঁটি) ফাংশনে প্রয়োগ করে। আমি প্রায়শই mainলাইন বরাবর কোড দেখি

main=getContents>>=print.foo

যখন

main=interact$show.foo

বেশ খানিকটা খাটো। এটি প্রিলোডে তাই আমদানির কোনও প্রয়োজন নেই!


24

জিএইচসি 7.10 ব্যবহার করুন

জিএইচসি-র প্রথম সংস্করণ যাতে এই স্টাফটি রয়েছে 27 শে মার্চ, 2015 এ প্রকাশিত হয়েছিল ।

এটি সর্বশেষতম সংস্করণ, এবং প্রিলেডে এমন কিছু নতুন সংযোজন পেল যা গল্ফিংয়ের জন্য দরকারী:

(<$>)এবং (<*>)অপারেটরদের

এই দরকারী অপারেটরগুলি থেকে Data.Applicativeএটি তৈরি! <$>ঠিক হয় fmapতাই আপনি প্রতিস্থাপন করতে পারেন, map f xএবং fmap f xসঙ্গে f<$>xসর্বত্র এবং ফিরে বাইট জয়। এছাড়াও, তালিকাগুলির জন্য উদাহরণটিতে <*>দরকারী Applicative:

Prelude> (,)<$>[1..2]<*>"abcd"
[(1,'a'),(1,'b'),(1,'c'),(1,'d'),(2,'a'),(2,'b'),(2,'c'),(2,'d')]

(<$)অপারেটর

x<$aসমান fmap (const x) a; অর্থাত্ একটি পাত্রে প্রতিটি উপাদান প্রতিস্থাপন x

এটি প্রায়শই একটি দুর্দান্ত বিকল্প replicate: এর 4<$[1..n]চেয়ে সংক্ষিপ্ত replicate n 4

ভাঁজযোগ্য / অনুসরণযোগ্য প্রস্তাব

নিম্নলিখিত ফাংশনগুলি তালিকাতে কাজ করা [a]থেকে সাধারণ Foldableধরণের উপরে উঠেছে t a:

fold*, null, length, elem, maximum, minimum, sum, product
and, or, any, all, concat, concatMap

এর অর্থ হ'ল তারা এখন আরও কাজ করে Maybe a, যেখানে তারা "সর্বাধিক এক উপাদান সহ তালিকাগুলির" মতো আচরণ করে। উদাহরণস্বরূপ, null Nothing == Trueবা sum (Just 3) == 3। একইভাবে, মানগুলির জন্য length0 Nothingএবং 1 প্রদান করে Just। লেখার বদলে লিখতে x==Just yপারেন elem y x

আপনি এগুলিকে টিপলসেও প্রয়োগ করতে পারেন, যা এমনভাবে কাজ করে যা আপনি আগে কল করেছিলেন \(a, b) -> [b]। এটা প্রায় সম্পূর্ণ অকেজো, কিন্তু or :: (a, Bool) -> Boolএকাধিক চরিত্র খাটো snd, আর elem bচেয়ে খাটো (==b).snd

মনোয়েড ফাংশন memptyএবংmappend

প্রায়শই জীবন রক্ষাকারী নয়, তবে আপনি যদি ধরণটি নির্ধারণ করতে পারেন তবে তার memptyচেয়ে এক বাইট কম খাটান Nothing, তাই সেখানে।


5
+1 '<$> about সম্পর্কে শুনে <*>এবং এটি উপস্থাপিত করে তোলা দুর্দান্ত! কোড গল্ফ না থাকলেও এটি ব্যবহারযোগ্য হওয়া উচিত (প্রয়োগকারী এত দীর্ঘ শব্দ)।
ankh-morpork 22

ফ্ল্যাট প্রতিস্থাপন সম্পর্কে সতর্কতা: যদি আপনার ভাষার সংস্করণটি চ্যালেঞ্জের চেয়ে নতুন হয় তবে আপনার সমাধানটি জয়ের পক্ষে অযোগ্য। আপনি যদি আপনার বিদ্যমান উত্তর বা উত্তর আপডেট করতে চান তবে আপনার বিদ্যমান সমাধানটি ওভাররাইট করবেন না। একটি পরিশিষ্ট লিখুন।
জন ডিভোরাক

4
মজার সেখানে [1..2]আছে। এটা ঠিক[1,2]
গর্বিত হাসেলেলার

2
একই সংস্করণে আমরা পেয়েছিলাম <*থেকে Applicativeতালিকার জন্য যা, xs <* ys == concatMap (replicate (length ys)) xs। এটি xs >> ysবা xs *> ysযা থেকে পৃথক concat (replicate (length ys)) xspureএকটি সংক্ষিপ্ত যা returnএই সময়ে এসেছিল।
অ্যাঙ্গস

2
আপনি এখন এর <>পরিবর্তে ব্যবহার করতে পারেন mappend, এটি এখন (জিএইচসি 8.4.1 সহ) এর অংশ Prelude
:

22

এর 1<2পরিবর্তে Trueএবং 1>2পরিবর্তে ব্যবহার করুন False

g x|x<10=10|True=x
f x|x<10=10|1<2=x

3
এটি হাস্কেলের পক্ষে সত্যই সুনির্দিষ্ট নয়: এটি সত্যিকারের এবং অন্য ধরণের মিথ্যা মানগুলির বিপরীতে বুলিয়ান প্রকারের প্রায় প্রতিটি ভাষার ক্ষেত্রেই প্রযোজ্য।
পিটার টেলর

কেউ কি এই ব্যাখ্যা করতে পারেন?
মাস্টারমেস্টিক

2
এটি একটি ভাল উদাহরণ নয়, আমি এই হিসাবে গল্ফ হবে f=max 10
গর্বিত হাসেলেলার 14

@ মাস্টারমাস্টিক এটি কেবল if(true)অন্য ভাষায় লিখছেন । উপস্থাপিকাতে, অন্যথায় আসলে বুলিয়ান মান True
গর্বিত হাসেলেলার

2
@ পিটারটেলর আমি মনে করি যে এটি নতুন হাস্কেলিয়ানদের জন্য (আমার মতো) এখনও মূল্যবান বলে আমি প্রথম ব্যবহার করতে শিখেছি otherwise
flawr

20

তালিকা বোঝাপড়া (চালাক উপায়ে) ব্যবহার করুন

সকলেই জানেন যে তারা দরকারী সিনট্যাক্স, প্রায়শই mapএকটি ল্যাম্বডার চেয়ে ছোট :

Prelude> [[1..x]>>show x|x<-[1..9]]
["1","22","333","4444","55555","666666","7777777","88888888","999999999"]

বা filter(এবং mapএকই সময়ে বিকল্প হিসাবে একটি ):

Prelude> [show x|x<-[1..60],mod 60x<1]
["1","2","3","4","5","6","10","12","15","20","30","60"]

তবে কিছু অযৌক্তিক ব্যবহার রয়েছে যা এখন এবং পরে কাজে আসবে। একটির জন্য, একটি তালিকা বোঝার জন্য কোনও <-তীর ধারণ করার দরকার নেই :

Prelude> [1|False]
[]
Prelude> [1|True]
[1]

পরিবর্তে যার অর্থ if p then[x]else[], আপনি লিখতে পারেন [x|p]। এছাড়াও, শর্তটি সন্তুষ্ট করে একটি তালিকার উপাদানগুলির সংখ্যা গণনা করার জন্য, স্বজ্ঞাতভাবে আপনি লিখে ফেলবেন:

length$filter p x

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

sum[1|y<-x,p y]

আমি আসলে এই সমস্ত আগে ব্যবহার করেছি, তবে আমি এগুলি এখানে রাখার চিন্তা করি না।
গর্বিত হাস্কেলর

18

আপনার জানুন Prelude

GHCi ফায়ার করুন এবং প্রিলিওড ডকুমেন্টেশনের মাধ্যমে স্ক্রোল করুন । যখনই আপনি একটি সংক্ষিপ্ত নামযুক্ত কোনও ক্রিয়াকলাপটি অতিক্রম করবেন তখন কিছু ক্ষেত্রে এটি কার্যকর হতে পারে তা সন্ধান করতে অর্থ প্রদান করতে পারে।

উদাহরণস্বরূপ, ধরুন আপনি কোনও স্ট্রিংকে s = "abc\ndef\nghi"স্থান-বিচ্ছিন্নভাবে রূপান্তর করতে চান "abc def ghi"। সুস্পষ্ট উপায় হ'ল:

unwords$lines s

তবে আপনি অপব্যবহার করলে maxএবং আরও ভাল আপনি করতে পারেন \n < space < printable ASCII:

max ' '<$>s

আরেকটি উদাহরণ হ'ল lex :: String -> [(String, String)], যা বেশ রহস্যজনক কিছু করে:

Prelude> lex "   some string of Haskell tokens  123  "
[("some"," string of Haskell tokens  123  ")]

fst=<<lex sহোয়াইটস্পেস এড়িয়ে স্ট্রিং থেকে প্রথম টোকেন পাওয়ার চেষ্টা করুন । এখানে হেনকমার একটি চতুর সমাধান যা মানগুলিতে ব্যবহার lex.showকরে Rational


16

একটি ধ্রুবক মান মেলে

একটি তালিকা বোধগতি ধ্রুবক উপর প্যাটার্ন মেলে পারে।


[0|0<-l]

এটি একটি তালিকার 0 গুলি বের করে l, অর্থাৎ যতগুলি 0 রয়েছে তার একটি তালিকা তৈরি করে l


[1|[]<-f<$>l] 

এটি খালি তালিকায় ( ইনফিক্স হিসাবে ব্যবহার করে ) 1এর উপাদান রয়েছে বলে lএটি অনেকের একটি তালিকা তৈরি fকরে । এই উপাদানগুলি গণনা করতে প্রয়োগ করুন ।<$>mapsum

তুলনা করা:

[1|[]<-f<$>l]
[1|x<-l,f x==[]]

[x|(0,x)<-l]

প্যাটার্ন ম্যাচের অংশ হিসাবে ধ্রুবক ব্যবহার করা যেতে পারে। এটি এমন সমস্ত টিপলসের দ্বিতীয় প্রবেশিকা বের করে যার প্রথম প্রবেশিকা 0


নোট করুন যে এগুলিগুলির জন্য একটি ভেরিয়েবলের মান নয়, একটি আসল ধ্রুবক আক্ষরিক প্রয়োজন। উদাহরণস্বরূপ, let x=1 in [1|x<-[1,2,3]]আউটপুট হবে [1,1,1]না [1], কারণ বাইরের xবাইন্ডিং ওভাররাইট করা হয়েছে।


14

wordsস্ট্রিংগুলির দীর্ঘ তালিকার পরিবর্তে ব্যবহার করুন । এটি হাস্কেলের সাথে সত্যই নির্দিষ্ট নয়, অন্যান্য ভাষায়ও একই কৌশল রয়েছে।

["foo","bar"]
words"foo bar"  -- 1 byte longer
["foo","bar","baz"]
words"foo bar baz"  -- 1 byte shorter
["foo","bar","baz","qux"]
words"foo bar baz qux"    -- 3 bytes shorter

14

আপনার monadic ফাংশন জানুন

1)
ব্যবহার করে monadic ফাংশন অনুকরণ mapM

অনেক সময় কোড থাকবে sequence(map f xs)তবে এটি দিয়ে প্রতিস্থাপন করা যাবে mapM f xs। এমনকি যখন কেবল sequenceএকা ব্যবহার করার পরে এটি দীর্ঘ হয় mapM id

2) (বা )
ব্যবহার করে ফাংশনগুলি একত্রিত করুন(>>=)(=<<)

এর ফাংশন মোনাড সংস্করণটি (>>=)তাই হিসাবে সংজ্ঞায়িত করা হয়েছে:

(f >>= g) x = g (f x) x 

এটি ফাংশন তৈরির জন্য কার্যকর হতে পারে যা পাইপলাইন হিসাবে প্রকাশ করা যায় না। উদাহরণস্বরূপ, এর \x->x==nub xচেয়ে দীর্ঘ nub>>=(==)এবং \t->zip(tail t)tদীর্ঘ থেকে দীর্ঘ tail>>=zip


+1 - আমি এমনকি বুঝতে পারি নি যে ফাংশনগুলির জন্য একটি মোনাড উদাহরণ রয়েছে। যে খুব কুশলী :) হতে পারে
জুলে

2
পার্শ্ব দ্রষ্টব্য: যদিও এটি এর অংশ Applicativeএবং না Monadএর বাস্তবায়নও এর pureচেয়ে কম যা constপ্রকৃতপক্ষে আমাকে আগে সাহায্য করেছিল।
0

14

সংজ্ঞা সংজ্ঞা চেয়ে ছোট হতে পারে

আমি হেনকমা দ্বারা খুব কৌতূহলীভাবে মাত্র ছড়িয়ে পড়েছি

একটি অক্জিলিয়ারী ফাংশন যদি fআপনার উত্তর একটি অপারেটর যে আপনার উত্তর অন্যত্র ব্যবহার করা, এবং ব্যবহার fএকবার বলা হয়, অপারেটর একটি আর্গুমেন্ট করা f

এই:

(!)=take
f a=5!a++3!a
reverse.f

এর চেয়ে দুটি বাইট দীর্ঘ:

f(!)a=5!a++3!a
reverse.f take

12

কনস অপারেটর ব্যবহার করুন (:)

তালিকার সাথে তাল মিলিয়ে যখন প্রথম দৈর্ঘ্য 1 হয় তবে তার :পরিবর্তে ব্যবহার করুন।

a++" "++b
a++' ':b  -- one character shorter

[3]++l
3:l    -- three characters shorter

4
তিনি লক্ষ করেন এটা ঠিক মিশুক, তাই আপনি তালিকার শুরুতে যেমন এ একক আইটেম যে কোন সংখ্যার জন্য এটি ব্যবহার রাখতে পারবেন না ওয়ার্থ 1:2:3:xবদলে [1,2,3]++x
জুলে

11

খুব ঘন ঘন ব্যাকটিক্স ব্যবহার করবেন না। ব্যাকটিক্স প্রিফিক্স ফাংশনগুলির বিভাগগুলি তৈরি করার জন্য একটি দুর্দান্ত সরঞ্জাম, তবে কখনও কখনও এটির অপব্যবহারও করা যায়।

একবার আমি কাউকে এই সুপ্রেসপশন লিখতে দেখেছি:

(x`v`)

যদিও এটি ঠিক হিসাবে একই v x

অন্য একটি উদাহরণ (x+1)`div`y বিরোধিতা হিসাবে লেখা div(x+1)y

আমি প্রায়শই divএবং elemপ্রায়শই ঘটতে দেখি কারণ এই ফাংশনগুলি সাধারণত নিয়মিত কোডে ইনফিক্স হিসাবে ব্যবহৃত হয়।


আপনি কি উপসর্গ ফাংশন বিভাগ তৈরি করা মানে না ?
সাইয়েস

@ কিউস হ্যাঁ, অবশ্যই
গর্বিত হাসেলেলার

11

প্যাটার্ন গার্ড ব্যবহার করুন

এগুলি একটি letবা ল্যাম্বডারের চেয়ে সংক্ষিপ্ত যা আপনার দ্বারা সংজ্ঞায়িত করা ফাংশনটির যুক্তিগুলি ডিকনস্ট্রাক্ট করে। এই সাহায্য করে যখন আপনি ভালো কিছু প্রয়োজন fromJustথেকে Data.Maybe:

f x=let Just c=… in c

এর চেয়ে লম্বা

f x=(\(Just c)->c)$…

এর চেয়ে লম্বা

m(Just c)=c;f x=m$…

এর চেয়ে লম্বা

f x|Just c<-…=c

প্রকৃতপক্ষে, ডিকনস্ট্রাকচারিংয়ের পরিবর্তে সরল পুরানো মানকে আবদ্ধ করার সময়ও তারা খাটো হয়: এক্সনরের টিপ দেখুন


ঠিক আছে, ল্যাম্বডা কারও জন্য ডলারের চিহ্নের প্রয়োজন নেই, এবং মনে হচ্ছে এই পরিবর্তনটি এর দৈর্ঘ্য এবং পরবর্তী স্নিপেট একই করে
গর্বিত হাসেলেলার

1
আমি ধরে নিচ্ছি eআসলে একটি টোকেন নয় বরং এর চেয়ে বেশি দীর্ঘ অভিব্যক্তি যা এর $আগে প্রয়োজন।
লিন

11

শর্তসাপেক্ষ ছোট

last$x:[y|b]

সমতুল্য

if b then y else x

এখানে কিভাবে এটা কাজ করে:

             [y|b]   x:[y|b]   last$x:[y|b]
if...      +--------------------------------
b == False | []      [x]       x
b == True  | [y]     [x,y]     y

এটা করা উচিত if b then y else x?
আকংকা

@ ক্রিশ্চিয়ান ইরান ভাল হ্যাচ, ভাল।
xnor

boolআপনার কোনও তালিকা বোঝার প্রয়োজন না হওয়ায় সংক্ষিপ্ত হতে ব্যবহার করতে চান
আলু 44

@ আলু 44 এটি ডেটা-বুলে রয়েছে, যা আমদানি করতে বাইট খরচ হয়।
xnor

11

বিয়োগ চিহ্ন নিয়ে কাজ করা

বিয়োগ চিহ্নটি -অনেক সিনট্যাক্স নিয়মের বিরক্তিকর ব্যতিক্রম। এই টিপটি হ্যাসকেলে অবজ্ঞা ও বিয়োগ প্রকাশ করার কয়েকটি সংক্ষিপ্ত উপায়ের তালিকাবদ্ধ করে। আমি কিছু মিস করেছি কিনা দয়া করে আমাকে জানান।

অস্বীকৃতি

  • একটি অভিব্যক্তি অবহেলা করতে e, ঠিক না -e। উদাহরণস্বরূপ, -length[1,2]দেয় -2
  • eএমনকি যদি মাঝারিভাবে জটিল হয় eতবে আপনার চারপাশে প্রথম বন্ধনী প্রয়োজন হবে তবে আপনি সাধারণত একটি বাইটগুলি এদিক ওদিক ঘুরিয়ে বাঁচাতে পারেন: এর -length(take 3 x)চেয়ে সংক্ষিপ্ত -(length$take 3 x)
  • যদি eএর আগে =বা 6 এর চেয়ে কম স্থিরতার একটি ইনফিক্স অপারেটর থাকে তবে আপনার একটি স্থান প্রয়োজন: f= -2সংজ্ঞাযুক্ত fএবং এর চেয়ে কম k< -2হলে পরীক্ষা করুন । স্থিরতা যদি 6 বা তার বেশি হয় তবে আপনার প্যারেন্স দরকার: দেয় । এগুলি থেকে মুক্তি পেতে আপনি সাধারণত জিনিসগুলি পুনরায় সাজিয়ে নিতে পারেন: উদাহরণস্বরূপ, এর পরিবর্তে করুন ।k-22^^(-2)0.25-k>2k< -2
  • একইভাবে, যদি !অপারেটর হয়, তবে -a!bপার্স করা হয় (-a)!bযেন স্থিরতা !সর্বোচ্চ 6 (তাই -1<1দেয় True), এবং -(a!b)অন্যথায় (সুতরাং -[1,2]!!0দেয় -1)। ব্যবহারকারী-সংজ্ঞায়িত অপারেটর এবং ব্যাকটিকযুক্ত ফাংশনগুলির ডিফল্ট স্থিতি 9, তাই তারা দ্বিতীয় বিধি অনুসরণ করে।
  • অবহেলাটিকে কোনও ফাংশনে পরিণত করতে ( mapইত্যাদি ব্যবহার করতে) বিভাগটি ব্যবহার করুন (0-)

বিয়োগ

  • বিয়োগ করে এমন কোনও ফাংশন পেতে k, বিভাগটি ব্যবহার করুন (-k+)যা যুক্ত করে -kkএমনকি একটি জটিল জটিল ভাব হতে পারে: (-2*length x+)প্রত্যাশার মতো কাজ করে।
  • 1 বিয়োগ করতে, predপরিবর্তে ব্যবহার করুন, যদি না এটি উভয় পক্ষের একটি জায়গার প্রয়োজন হয়। এই বিরল এবং সাধারণত সঙ্গে ঘটবে until, অথবা একটি ব্যবহারকারী-সংজ্ঞায়িত ফাংশন যেহেতু map pred xদ্বারা প্রতিস্থাপিত হতে পারে pred<$>xএবং iterate pred xদ্বারা [x,x-1..]। এবং যদি আপনার f pred xকোথাও থাকে তবে আপনার সম্ভবত fকোনওভাবেই ইনফিক্স ফাংশন হিসাবে সংজ্ঞা দেওয়া উচিত । এই টিপ দেখুন ।

11

ফাংশন সংজ্ঞা এবং / বা তর্কগুলি পুনরায় সাজানোর চেষ্টা করুন

আপনি কখনও কখনও কোনও ফাংশন সংজ্ঞাতে প্যাটার্ন-মিলের মামলার ক্রম পরিবর্তন করে কয়েকটি বাইট সংরক্ষণ করতে পারেন। এই সঞ্চয়গুলি সস্তা, তবে উপেক্ষা করা সহজ।

উদাহরণ হিসাবে, এই উত্তরটির (পূর্ববর্তী অংশের) পূর্ববর্তী সংস্করণটি বিবেচনা করুন :

(g?x)[]=x
(g?x)(a:b)=g(g?x$b)a

এটি একটি পুনরাবৃত্ত সংজ্ঞা ?, বেস কেসটি খালি তালিকার সাথে। যেহেতু []কোনও দরকারী মূল্য নয় তাই আমাদের সংজ্ঞাগুলি অদলবদল করা উচিত এবং এটি একটি বাইট _সংরক্ষণ করে ওয়াইল্ডকার্ড বা একটি ডামি যুক্তির সাথে প্রতিস্থাপন করা উচিত y:

(g?x)(a:b)=g(g?x$b)a
(g?x)y=x

একই উত্তর থেকে, এই সংজ্ঞাটি বিবেচনা করুন:

f#[]=[]
f#(a:b)=f a:f#b

খালি তালিকাটি রিটার্ন মানতে ঘটে, তাই আমরা কেসগুলি অদলবদল করে দুটি বাইট সংরক্ষণ করতে পারি:

f#(a:b)=f a:f#b
f#x=x

এছাড়াও, ফাংশন আর্গুমেন্টের ক্রম কখনও কখনও আপনাকে অপ্রয়োজনীয় সাদা স্থান সরিয়ে দেওয়ার মাধ্যমে একটি পার্থক্য করতে পারে। এই উত্তরের পূর্ববর্তী সংস্করণটি বিবেচনা করুন :

h p q a|a>z=0:h p(q+2)(a-1%q)|1<2=1:h(p+2)q(a+1%p)

প্রথম শাখার মধ্যে hএবং শ্বেতস্পেসের এক বিরক্তিকর অংশ রয়েছে ph a p qপরিবর্তে সংজ্ঞা দিয়ে আমরা এ থেকে মুক্তি পেতে পারি h p q a:

h a p q|a>z=0:h(a-1%q)p(q+2)|1<2=1:h(a+1%p)(p+2)q

10

"অন্যথায়" প্রহরীকে অপচয় করবেন না

একটি চূড়ান্ত রক্ষক যা একটি ক্যাচ-অল True(সংক্ষিপ্ত 1>0) একটি ভেরিয়েবলকে বাঁধতে ব্যবহার করা যেতে পারে। তুলনা করা:

... |1>0=1/(x+y)
... |z<-x+y=1/z

... |1>0=sum l-sum m
... |s<-sum=s l-s m

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


10

রক্ষীদের ,পরিবর্তে ব্যবহার করুন&&

গার্ডের একাধিক শর্ত যা সমস্তকে ধারণ করতে হয় ,তার পরিবর্তে একত্রিত হতে পারে &&

f a b | a/=5 && b/=7 = ...
f a b | a/=5 ,  b/=7 = ...

2
f xs m | [x] <- xs, Just y <- m, x > 3 = y
এটিরও

10

স্থানীয় ঘোষণার জন্য সংক্ষিপ্ত বাক্য গঠন

কখনও কখনও আপনাকে একটি স্থানীয় ফাংশন বা অপারেটর সংজ্ঞায়িত করতে হবে তবে এটি লেখার জন্য whereবা let…inঅতিরিক্ত যুক্তি যুক্ত করে শীর্ষ স্তরে উন্নীত করতে প্রচুর বাইট খরচ করতে হয়।

g~(a:b)=2!g b where k!l=k:take(a-1)l++(k+1)!drop(a-1)l
g~(a:b)=let k!l=k:take(a-1)l++(k+1)!drop(a-1)l in 2!g b
g~(a:b)=2!g b$a;(k!l)a=k:take(a-1)l++((k+1)!drop(a-1)l)a

সৌভাগ্যক্রমে, হাস্কেলের স্থানীয় ঘোষণার জন্য একটি বিভ্রান্তিকর এবং খুব কম ব্যবহৃত হলেও যুক্তিসঙ্গতভাবে সংশ্লেষ রয়েছে :

fun1 pattern1 | let fun2 pattern2 = expr2 = expr1

এক্ষেত্রে:

g~(a:b)|let k!l=k:take(a-1)l++(k+1)!drop(a-1)l=2!g b

আপনি এই বাক্য গঠনটি মাল্টি-স্টেটমেন্ট ডিক্লেয়ারেশন বা একাধিক ঘোষণাপত্রের সাথে ব্যবহার করতে পারেন, এবং এটি বাসা বেঁধেছে:

fun1 pattern1 | let fun2 pattern2 = expr2; fun2 pattern2' = expr2' = expr1
fun1 pattern1 | let fun2 pattern2 = expr2; fun3 pattern3 = expr3 = expr1
fun1 pattern1 | let fun2 pattern2 | let fun3 pattern3 = expr3 = expr2 = expr1

এটি বাইন্ডিং ভেরিয়েবল বা অন্যান্য নিদর্শনগুলির জন্যও কাজ করে, যদিও প্যাটার্ন গার্ডরা এর জন্য আরও ছোট হয়ে থাকে যদি না আপনি যদি বাধ্যতামূলক ফাংশন না করেন তবে।


3
এই তালিকা comprehensions ভিতরে কাজ করে: [f 1|let f x=x+1]
লাইকনি

10

এড়াতে repeat n

-- 8 bytes, whitespace might be needed before and after
repeat n

-- 8 bytes, whitespace might be needed before
cycle[n]

-- 7 bytes, whitespace might be needed before and after, can be reused,
-- needs an assignment, n needs to be global
l=n:l;l

-- 7 bytes, never needs whitespace, n needs to derive from Enum,
-- n has to be short enough to be repeated twice
[n,n..]

এই চারটি অভিব্যক্তির মধ্যে একটিরই অসীম তালিকা তৈরি করবে n

এটি একটি খুব নির্দিষ্ট টিপ তবে এটি 3 বাইট পর্যন্ত সাশ্রয় করতে পারে !


4
যদি nবৈশ্বিক l=n:l;lহয় তবে এটি একই দৈর্ঘ্য এবং (কিছু) দীর্ঘ এক্সপ্রেশনগুলির জন্য কাজ করে। (যদিও হোয়াইটস্পেসের প্রয়োজন হতে পারে))
janrjan জোহানসেন

@ আরজান জোহানসেন আমি এটিকে পোস্টে অন্তর্ভুক্ত করেছি। ধন্যবাদ!
সম্পূর্ণমানবিক

10

একটি ফলাফল খালি তালিকা যখন সংক্ষিপ্ত শর্তসাপেক্ষ

যখন আপনার শর্তসাপেক্ষ দরকার যা কিছু শর্তের উপর নির্ভর করে তালিকাটি Aবা খালি তালিকা ফেরত দেয় , তখন সাধারণ শর্তাধীন কাঠামোর কিছু সংক্ষিপ্ত বিকল্প উপস্থিত থাকে:[]C

if(C)then(A)else[] -- the normal conditional
last$[]:[A|C]      -- the golfy all-round-conditional
concat[A|C]        -- shorter and works when surrounded by infix operator
id=<<[A|C]         -- even shorter but might conflict with other infix operators
[x|C,x<-A]         -- same length and no-conflict-guarantee™
[0|C]>>A           -- shortest way, but needs surrounding parenthesis more often than not

উদাহরণ: 1 , 2


দ্বিতীয়টি এসেছে Aএবং []স্যুইচ করেছে।
janrjan জোহানসেন

@ আরজান জোহানসেন সংশোধন করেছেন, ধন্যবাদ!
লাইকোনি

1
আহা! তবে *>এর চেয়ে বেশি স্থিরতা রয়েছে >>(স্বাচ্ছন্দ্যের জন্য এখনও কিছুটা কম)
janরঞ্জন জোহানসেন

9

লাম্বদা পার্সিং বিধি

একটি ল্যাম্বডা-এক্সপ্রেশনটির চারপাশে আসলে প্রথম বন্ধনী প্রয়োজন হয় না - এটি কেবল লোভের সাথে সমস্ত কিছু ধরে রাখে যাতে পুরো জিনিসটি এখনও বিশ্লেষণ করে, যেমন অবধি

  • একটি বন্ধ প্যারেন - (foo$ \x -> succ x)
  • একটি ইন - let a = \x -> succ x in a 4
  • লাইনের শেষে - main = getContents>>= \x -> head $ words x
  • ইত্যাদি ..

মুখোমুখি হয়েছে, এবং কিছু অদ্ভুত প্রান্ত-কেস রয়েছে যেখানে এটি আপনাকে একটি বা দুটি বাট বাঁচাতে পারে। আমি বিশ্বাস করি \অপারেটরগুলি সংজ্ঞায়িত করতেও ব্যবহার করা যেতে পারে, সুতরাং এটি ব্যবহার করার সময় কোনও অপারেটরের পরে সরাসরি ল্যাম্বদা লেখার সময় আপনার একটি স্থানের প্রয়োজন হবে (তৃতীয় উদাহরণের মতো)।

ল্যাম্বডা ব্যবহার করা আমার পক্ষে সংক্ষিপ্ততম জিনিসটি ছিল Here কোডটি মূলত:

a%f=...
f t=sortBy(% \c->...)['A'..'Z']

9

ল্যাম্বদা letদ্বারা প্রতিস্থাপন করুন

এটি সাধারণত কোনও একাকী সহায়ক সংজ্ঞা সংক্ষিপ্ত করতে পারে যা কোনও কারণে প্রহরী দ্বারা আবদ্ধ বা বিশ্বজুড়ে সংজ্ঞায়িত হতে পারে না । উদাহরণস্বরূপ, প্রতিস্থাপন করুন

let c=foo a in bar

3 বাইট ছোট দ্বারা

(\c->bar)$foo a

একাধিক সহায়ক সংজ্ঞা জন্য, সংজ্ঞা সংখ্যার উপর নির্ভর করে লাভ সম্ভবত কম।

let{c=foo a;n=bar a}in baz
(\c n->baz)(foo a)$bar a

let{c=foo a;n=bar a;m=baz a}in qux
(\c n m->qux)(foo a)(bar a)$baz a

let{c=foo a;n=bar a;m=baz a;l=qux a}in quux
(\c n m l->quux)(foo a)(bar a)(baz a)$qux a

কিছু সংজ্ঞা অন্যকে বোঝায়, এইভাবে বাইটগুলি সংরক্ষণ করা আরও শক্ত:

let{c=foo a;n=bar c}in baz
(\c->(\n->baz)$bar c)$foo a

এর সাথে প্রধান সতর্কতা হ'ল এটি letআপনাকে বহুবর্ষীয় ভেরিয়েবলগুলি সংজ্ঞায়িত করতে দেয় তবে ল্যাম্বডাস @ ক্রিশ্চিয়ানসিভার দ্বারা উল্লিখিত হিসাবে নয়। উদাহরণ স্বরূপ,

let f=length in(f["True"],f[True])

ফলাফল (1,1), কিন্তু

(\f->(f["True"],f[True]))length

একটি টাইপ ত্রুটি দেয়।


1
এটি খুব কমই গুরুত্বপূর্ণ, তবে "শব্দার্থ সমতুল্য" কিছুটা বেশি প্রতিশ্রুতি দেয়। আমাদের পলিমার্পিক রয়েছে let, তাই আমরা করতে পারি let f=id in (f 0,f True)। আমরা যদি ল্যাম্বদা দিয়ে এটি আবার লেখার চেষ্টা করি তবে এটি চেক টাইপ করে না।
ক্রিশ্চিয়ান সিভারস 21

@ খ্রিস্টিয়ানসিভারস এটি সত্য, নোটের জন্য ধন্যবাদ। আমি এটি সম্পাদনা করেছি
Zgarb

8

প্রহরী ব্যবহার করে বাঁধুন

কোনও নামকরণের ক্রিয়াটি সংজ্ঞায়িত করার সময়, আপনি কোনও গার্ডের মধ্যে একটি ভেরিয়েবলের সাথে একটি এক্সপ্রেশন বাঁধতে পারেন। উদাহরণ স্বরূপ,

f s|w<-words s=...

হিসাবে একই

f s=let w=words s in ...
f s=(\w->...)$words s

পুনরাবৃত্তি প্রকাশে সংরক্ষণ করতে এটি ব্যবহার করুন। যখন অভিব্যক্তিটি দু'বার ব্যবহৃত হয়, তখন এটি দৈর্ঘ্য 6 এও ভেঙে যায়, যদিও ব্যবধান এবং অগ্রাধিকারের সমস্যাগুলি এটি পরিবর্তন করতে পারে।

(উদাহরণস্বরূপ, যদি আসল ভেরিয়েবল sব্যবহার না করা হয় তবে এটি করা ছোট orter

g w=...
f=g.words

তবে এটি আরও জটিল এক্সপ্রেশন বন্ধনের জন্য সত্য নয়))


এই উত্তরটির সদৃশ / বিশেষ মামলা নয় ?
লিন

@ লিন পিছনে ফিরে তাকান, এটি একটি বিশেষ ঘটনা, তবে আমি যখন এই উত্তরটি পড়ি, Justউদাহরণটি আমাকে ভাবিয়ে তোলে যে এটি কোনও বাক্সে সঞ্চয় করার পরিবর্তে ধারক থেকে উত্তোলনের জন্য প্যাটার্ন-মিলের জন্য।
এক্সনর

8

তুলনার জন্য (0<$)পরিবর্তে ব্যবহার করুনlength

একটি তালিকা যদি তালিকার aচেয়ে দীর্ঘ হয় তবে পরীক্ষার bসময় সাধারণত একটি লিখতে পারে

length a>length b

তবে উভয় তালিকার প্রতিটি উপাদানকে একই মান, উদাহরণস্বরূপ প্রতিস্থাপন 0এবং তারপরে এই দুটি তালিকার তুলনা আরও কম করা যেতে পারে:

(0<$a)>(0<$b)

এটি অনলাইন চেষ্টা করুন!

প্রথম বন্ধনী কারণ প্রয়োজন হয় <$এবং তুলনা অপারেটরদের ( ==, >, <=, ...), যদিও কিছু অন্যান্য ক্ষেত্রে তারা প্রয়োজন না হতে পারে, একই প্রাধান্য স্তর 4 আছে আরও বেশি বাইট সংরক্ষণ।


8

অপেক্ষাকৃত ছোট transpose

transposeফাংশনটি ব্যবহার Data.Listকরতে আমদানি করতে হবে। যদি এটিই কেবল আমদানির প্রয়োজন হয় তবে নিম্নলিখিত foldrসংজ্ঞাটি ব্যবহার করে একটি বাইট সংরক্ষণ করতে পারে transpose:

import Data.List;transpose
e=[]:e;foldr(zipWith(:))e

নোট করুন যে আচরণটি একই দৈর্ঘ্যের তালিকাগুলির তালিকার জন্য অভিন্ন।

আমি এখানে এটি সফলভাবে ব্যবহার করেছি ।


8

প্রত্যয় পান

scanr(:)[]একটি তালিকার প্রত্যয় পেতে ব্যবহার করুন :

λ scanr(:)[] "abc"
["abc","bc","c",""]

এটি tailsপরের তুলনায় অনেক খাটো import Data.List। আপনি scanr(\_->init)=<<id(অর্জান জোহানসেনের দ্বারা পাওয়া) এর সাথে উপসর্গগুলি করতে পারেন ।

λ  scanr(\_->init)=<<id $ "abc"
["","a","ab","abc"]

এটি একটি বাইট ওভার সাশ্রয় করে

scanl(\s c->s++[c])[]

সম্ভবত scanl(flip(:))[] "abc"= ["","a","ba","cba"]উল্লেখ করার মতোও - কখনও কখনও উপসর্গগুলি পিছনের দিকে হওয়া কোনও বিষয় নয়।
লিন

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