এফ #-তে নেস্টনেসনেস-এর নির্বিচার স্তরের তালিকাগুলির সংমিশ্রণ


10

আমি একটি এফ # ফাংশন তৈরি করার চেষ্টা করছি intযা স্বেচ্ছাসেবী নেস্টনেসগুলির তালিকার যোগফলকে ফিরিয়ে দেবে। অর্থাৎ। এটি a list<int>, a list<list<int>>এবং a এর জন্য কাজ করবে list<list<list<list<list<list<int>>>>>>

হাসকেলে আমি এমন কিছু লিখতাম:

class HasSum a where
    getSum :: a -> Integer

instance HasSum Integer where
    getSum = id

instance HasSum a => HasSum [a] where
    getSum = sum . map getSum

যা আমাকে করতে দেয়:

list :: a -> [a]
list = replicate 6

nestedList :: [[[[[[[[[[Integer]]]]]]]]]]
nestedList =
    list $ list $ list $ list $ list $
    list $ list $ list $ list $ list (1 :: Integer)

sumNestedList :: Integer
sumNestedList = getSum nestedList

আমি কীভাবে এফ # তে এটি অর্জন করতে পারি?


1
আমি যথেষ্ট পরিমাণে এফ # জানি না - আমি জানি না যে এটি হাস্কেলের টাইপক্লাসগুলির মতো কিছু সমর্থন করে কিনা। সবচেয়ে খারাপ ক্ষেত্রে, আপনি স্পষ্টত অভিধানগুলি পাস করতে সক্ষম হবেন যদিও এটি হাস্কেলের মতো সুবিধাজনক নয় যেখানে সংকলকটি আপনার জন্য সঠিক অভিধানগুলি অনুমান করে। এই জাতীয় ক্ষেত্রে এফ # কোড এমন কিছু হবে getSum (dictList (dictList (..... (dictList dictInt)))) nestedListযেখানে সংখ্যার সাথে dictListমিলিত []হয় টাইপের সংখ্যার সাথে nestedList
চি

আপনি কি এই হ্যাশেল কোডটি একটি আরপিএল-তে চালিত করতে পারবেন?
ফিলিপ কারভালহো

আপনি এখানে যান ... repl.it/repls/BlondCoolParallelport
করাকফা

এফ # এর টাইপ ক্লাস নেই ( github.com/fsharp/fslang-suggestions/issues/243 )। আমি অপারেটরটিকে ওভারলোডিং ট্রিকটি চেষ্টা করেছি যা তত্ত্বটি কার্যকরভাবে কাজ করতে পারে তবে আমি কেবল সংক্ষেপকটি ক্র্যাশ করতে সক্ষম হয়েছি তবে সম্ভবত আপনি কৌশলটি কিছু তৈরি করতে পারেন: stackoverflow.com/a/8376001/418488
ঠিক আরও একটি রূপক

2
আপনার কোনও প্রয়োজন এমন কোনও বাস্তববাদী এফ # কোডবেস কল্পনা করতে পারি না। এটি করার জন্য আপনার প্রেরণা কী ছিল? আমি সম্ভবত নকশাটি পরিবর্তন করব যাতে আপনি এরকম পরিস্থিতিতে না পড়েন - এটি সম্ভবত আপনার এফ # কোডটিকে আরও ভাল করে তুলবে।
টমাস পেট্রিসেক

উত্তর:


4

হালনাগাদ

আমি ($)সদস্যের পরিবর্তে অপারেটর ব্যবহার করে একটি সহজ সংস্করণ পেয়েছি । Https://stackoverflow.com/a/7224269/4550898 দ্বারা অনুপ্রাণিত :

type SumOperations = SumOperations 

let inline getSum b = SumOperations $ b // <-- puting this here avoids defaulting to int

type SumOperations with
    static member inline ($) (SumOperations, x  : int     ) = x 
    static member inline ($) (SumOperations, xl : _   list) = xl |> List.sumBy getSum

বাকি ব্যাখ্যাগুলি এখনও প্রয়োগ হয় এবং এটি দরকারী ...

আমি এটি সম্ভব করার একটি উপায় খুঁজে পেয়েছি:

let inline getSum0< ^t, ^a when (^t or ^a) : (static member Sum : ^a -> int)> a : int = 
    ((^t or ^a) : (static member Sum : ^a -> int) a)

type SumOperations =
    static member inline Sum( x : float   ) = int x
    static member inline Sum( x : int     ) =  x 
    static member inline Sum(lx : _   list) = lx |> List.sumBy getSum0<SumOperations, _>

let inline getSum x = getSum0<SumOperations, _> x

2                  |> getSum |> printfn "%d" // = 2
[ 2 ; 1 ]          |> getSum |> printfn "%d" // = 3
[[2; 3] ; [4; 5] ] |> getSum |> printfn "%d" // = 14

আপনার উদাহরণ চলছে:

let list v = List.replicate 6 v

1
|> list |> list |> list |> list |> list
|> list |> list |> list |> list |> list
|> getSum |> printfn "%d" // = 60466176

এটি সদস্য সীমাবদ্ধতার সাথে এসআরটিপি ব্যবহারের উপর ভিত্তি করে:, static member Sumসীমাবদ্ধতার জন্য কোনও সদস্যকে টাইপ করা দরকার যা তাকে Sum রিটার্ন দেয় int। এসআরটিপি ব্যবহার করার সময় জেনেরিক ফাংশনগুলি হওয়া দরকার inline

এটা কঠিন অংশ নয়। শক্ত অংশটি Sumএকটি বিদ্যমান ধরণের মতো সদস্যকে "যুক্ত" করছে intএবং Listযা অনুমোদিত নয়। কিন্তু, আমরা এটা একটি নতুন ধরনের যোগ করতে পারেন SumOperationsএবং বাধ্যতা অন্তর্ভুক্ত (^t or ^a) যেখানে ^tসবসময় হতে যাচ্ছে SumOperations

  • getSum0Sumসদস্য সীমাবদ্ধতা ঘোষণা করে এবং অনুরোধ করে।
  • getSumSumOperationsপ্রথম ধরণের প্যারামিটার হিসাবে পাস করেgetSum0

static member inline Sum(x : float ) = int xসংযোগকারীকে জেনেরিক ডায়নামিক ফাংশন কলটি ব্যবহার করতে রাজি করা এবং কল করার static member inline Sum(x : int )সময় কেবল ডিফল্ট নয় TheList.sumBy

আপনি দেখতে পাচ্ছেন যে কিছুটা সংশ্লেষিত, সিনট্যাক্সটি জটিল এবং সংকলকটিতে কয়েকটি quirks চারপাশে কাজ করা প্রয়োজন ছিল তবে শেষ পর্যন্ত এটি সম্ভব হয়েছিল।

এই পদ্ধতিটি অ্যারে, টিপলস, বিকল্পগুলি ইত্যাদির সাথে বা আরও সংজ্ঞা যুক্ত করে তাদের কোনও সংমিশ্রণের সাথে কাজ করার জন্য বাড়ানো যেতে পারে SumOperations:

type SumOperations with
    static member inline ($) (SumOperations, lx : _   []  ) = lx |> Array.sumBy getSum
    static member inline ($) (SumOperations, a  : ^a * ^b ) = match a with a, b -> getSum a + getSum b 
    static member inline ($) (SumOperations, ox : _ option) = ox |> Option.map getSum |> Option.defaultValue 0

(Some 3, [| 2 ; 1 |]) |> getSum |> printfn "%d" // = 6

https://dotnetfiddle.net/03rVWT


এটি একটি দুর্দান্ত সমাধান! তবে কেন কেবল পুনরাবৃত্তি বা ভাঁজ হবে না?
s952163

4
পুনরাবৃত্তি এবং ভাঁজ বিভিন্ন ধরণের পরিচালনা করতে পারে না। যখন জেনেরিক রিকার্সিভ ফাংশনটি তাত্ক্ষণিক হয় তখন এটি পরামিতিগুলির প্রকারটি ঠিক করে। এই ক্ষেত্রে যে কলে Sumসহজ ধরনের সঙ্গে সম্পন্ন করা হয়: Sum<int list list list>, Sum<int list list>, Sum<int list>, Sum<int>
এমিয়ার্স

2

এখানে রানটাইম সংস্করণটি সমস্ত নেট নেট সংগ্রহের সাথে কাজ করবে। যাইহোক, রানটাইম ব্যতিক্রমগুলির জন্য এমিয়েরের জবাব এবং এমিয়েরেসের সংকলক ত্রুটিগুলি এক্সচেঞ্জগুলিও 36x দ্রুত।

let list v = List.replicate 6 v

let rec getSum (input:IEnumerable) =
    match input with
    | :? IEnumerable<int> as l -> l |> Seq.sum
    | e -> 
        e 
        |> Seq.cast<IEnumerable> // will runtime exception if not nested IEnumerable Types
        |> Seq.sumBy getSum


1 |> list |> list |> list |> list |> list
|> list |> list |> list |> list |> list |> getSum // = 60466176

benchmarks

|    Method |        Mean |     Error |    StdDev |
|---------- |------------:|----------:|----------:|
| WeirdSumC |    76.09 ms |  0.398 ms |  0.373 ms |
| WeirdSumR | 2,779.98 ms | 22.849 ms | 21.373 ms |

// * Legends *
  Mean   : Arithmetic mean of all measurements
  Error  : Half of 99.9% confidence interval
  StdDev : Standard deviation of all measurements
  1 ms   : 1 Millisecond (0.001 sec)

1
এটি ভালভাবে কাজ করে, যদিও লক্ষণীয়ভাবে ধীর গতিতে: এটি 10 ​​বার চালানো অন্যান্য সমাধানের সাথে 1 সেকেন্ডের তুলনায় 56 সেকেন্ড সময় নিয়েছিল।
এমিয়ার্স

ইম্প্রেসিভ বেঞ্চমার্কিং! আপনি কি ব্যবহার করেছেন?
এমিয়ার্স

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