Я пытаюсь создать функцию F #, которая будет возвращать сумму списка int
s произвольной вложенности. То есть. это будет работать для 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
Как я могу добиться этого в F #?
getSum (dictList (dictList (..... (dictList dictInt)))) nestedList
где числоdictList
совпадений с числом[]
в типеnestedList
.Ответы:
ОБНОВИТЬ
Я нашел более простую версию с использованием оператора
($)
вместо члена. Вдохновленный https://stackoverflow.com/a/7224269/4550898 :Остальная часть объяснения все еще применима, и это полезно ...
Я нашел способ сделать это возможным:
Запуск вашего примера:
Это основано на использовании SRTP с ограничениями членов:
static member Sum
ограничение требует, чтобы тип вызывал член,Sum
который возвращаетint
. При использовании SRTP должны быть общие функцииinline
.Это не сложная часть. Твердая часть «добавление»
Sum
элемента к существующему типу , какint
иList
, не допускается. Но мы можем добавить его к новому типуSumOperations
и включить в ограничение,(^t or ^a)
где^t
оно всегда будетSumOperations
.getSum0
объявляетSum
ограничение члена и вызывает его.getSum
передаетSumOperations
в качестве параметра первого типаgetSum0
Строка
static member inline Sum(x : float ) = int x
была добавлена, чтобы убедить компилятор использовать общий динамический вызов функции, а не только значение по умолчаниюstatic member inline Sum(x : int )
при вызовеList.sumBy
Как вы можете видеть, это немного запутанно, синтаксис сложен, и было необходимо обойти некоторые причуды в компиляторе, но в конце концов это стало возможным.
Этот метод можно расширить для работы с массивами, кортежами, параметрами и т. Д. Или любой их комбинацией, добавив дополнительные определения в
SumOperations
:https://dotnetfiddle.net/03rVWT
источник
Sum
осуществляется с помощью более простого типа:Sum<int list list list>
,Sum<int list list>
,Sum<int list>
,Sum<int>
.Вот версия времени выполнения, будет работать со всеми коллекциями .net. Тем не менее, обменивается ошибками компилятора в ответе AMieres на исключения во время выполнения и AMieres 'также в 36 раз быстрее.
Ориентиры
источник