কৌশলটি হ'ল টাইপ ক্লাস ব্যবহার করা। এর ক্ষেত্রে printfকীটি হ'ল PrintfTypeটাইপ শ্রেণি। এটি কোনও পদ্ধতি প্রকাশ করে না, তবে গুরুত্বপূর্ণ অংশটি যাইহোক প্রকারভেদে রয়েছে।
class PrintfType r
printf :: PrintfType r => String -> r
সুতরাং printfএকটি ওভারলোডেড রিটার্ন টাইপ আছে। তুচ্ছ মামলায়, আমাদের কোনও অতিরিক্ত যুক্তি নেই, তাই আমাদের তাত্ক্ষণিকভাবে সক্ষম হতে rহবে IO ()। এই জন্য, আমাদের উদাহরণ আছে
instance PrintfType (IO ())
এর পরে, একটি পরিবর্তনশীল সংখ্যক আর্গুমেন্ট সমর্থন করার জন্য, আমাদের ইনস্ট্যান্স স্তরে পুনরাবৃত্তি ব্যবহার করা উচিত। বিশেষত আমাদের একটি উদাহরণ প্রয়োজন যাতে যদি rহয় তবে PrintfTypeএকটি ফাংশনের ধরণটিও x -> rএকটি PrintfType।
-- instance PrintfType r => PrintfType (x -> r)
অবশ্যই, আমরা কেবল যুক্তিগুলিকে সমর্থন করতে চাই যা আসলে ফর্ম্যাট করা যায়। দ্বিতীয় ধরণের ক্লাসটি এখানে PrintfArgআসে So সুতরাং আসল উদাহরণটি
instance (PrintfArg x, PrintfType r) => PrintfType (x -> r)
এখানে একটি সরলীকৃত সংস্করণ যা Showশ্রেণিতে অনেকগুলি আর্গুমেন্ট নেয় এবং কেবল সেগুলি মুদ্রণ করে:
{-# LANGUAGE FlexibleInstances #-}
foo :: FooType a => a
foo = bar (return ())
class FooType a where
bar :: IO () -> a
instance FooType (IO ()) where
bar = id
instance (Show x, FooType r) => FooType (x -> r) where
bar s x = bar (s >> print x)
এখানে, barএকটি আইও পদক্ষেপ গ্রহণ করে যা পুনরুক্তি দিয়ে তৈরি করা হয় যতক্ষণ না আর কোনও যুক্তি না উপস্থিত থাকে, যার পর্যায়ে আমরা কেবল এটি সম্পাদন করি।
*Main> foo 3 :: IO ()
3
*Main> foo 3 "hello" :: IO ()
3
"hello"
*Main> foo 3 "hello" True :: IO ()
3
"hello"
True
কুইকচেক একই কৌশলটি ব্যবহার করে, যেখানে Testableক্লাসে বেস কেসগুলির জন্য উদাহরণ রয়েছে Boolএবং ফাংশনগুলির জন্য পুনরাবৃত্তকারী যা Arbitraryক্লাসে যুক্তি গ্রহণ করে ।
class Testable a
instance Testable Bool
instance (Arbitrary x, Testable r) => Testable (x -> r)