Saya mencoba membuat fungsi F # yang akan mengembalikan jumlah daftar dari int
nestedness yang berubah-ubah. Yaitu. itu akan bekerja untuk list<int>
alist<list<int>>
dan a list<list<list<list<list<list<int>>>>>>
.
Di Haskell saya akan menulis sesuatu seperti:
class HasSum a where
getSum :: a -> Integer
instance HasSum Integer where
getSum = id
instance HasSum a => HasSum [a] where
getSum = sum . map getSum
yang akan membiarkan saya melakukannya:
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
Bagaimana saya bisa mencapai ini di F #?
getSum (dictList (dictList (..... (dictList dictInt)))) nestedList
mana jumlahdictList
cocok dengan jumlah[]
dalam tipenestedList
.Jawaban:
MEMPERBARUI
Saya menemukan versi yang lebih sederhana menggunakan operator dan
($)
bukan anggota. Terinspirasi oleh https://stackoverflow.com/a/7224269/4550898 :Penjelasan lainnya masih berlaku dan ini berguna ...
Saya menemukan cara untuk memungkinkannya:
Menjalankan contoh Anda:
Ini didasarkan pada penggunaan SRTP dengan batasan anggota:,
static member Sum
batasan tersebut mengharuskan jenis untuk memiliki anggota yang dipanggilSum
yang mengembalikan sebuahint
. Saat menggunakan SRTP, fungsi generik harusinline
.Itu bukan bagian yang sulit. Bagian yang sulit adalah "menambahkan"
Sum
anggota ke tipe seperti yang adaint
danList
yang tidak diizinkan. Tapi, kita bisa menambahkannya ke tipe baruSumOperations
dan memasukkan dalam batasan di(^t or ^a)
mana^t
akan selalu adaSumOperations
.getSum0
mendeklarasikanSum
batasan anggota dan memintanya.getSum
lolosSumOperations
sebagai parameter tipe pertama kegetSum0
Baris
static member inline Sum(x : float ) = int x
ditambahkan untuk meyakinkan kompiler untuk menggunakan panggilan fungsi dinamis generik dan bukan hanya defaultstatic member inline Sum(x : int )
ketika meneleponList.sumBy
Seperti yang Anda lihat sedikit berbelit-belit, sintaksisnya kompleks dan perlu untuk mengatasi beberapa keanehan pada kompiler tetapi pada akhirnya itu mungkin.
Metode ini dapat diperluas untuk bekerja dengan Array, tuple, opsi, dll. Atau kombinasi dari semuanya dengan menambahkan lebih banyak definisi ke
SumOperations
:https://dotnetfiddle.net/03rVWT
sumber
Sum
dilakukan dengan jenis sederhana:Sum<int list list list>
,Sum<int list list>
,Sum<int list>
,Sum<int>
.Berikut adalah versi runtime, akan berfungsi dengan semua koleksi .net. Namun, bertukar kesalahan kompiler dalam jawaban AMieres untuk pengecualian runtime dan AMieres 'juga lebih cepat 36x.
Tolak ukur
sumber