полиморфизм haskell и списки

Это в основном тот же механизм, что и для команды без запроса с:

  • command.CommandText = имя хранимой процедуры
  • command.CommandType = CommandType.StoredProcedure
  • Столько обращений к команде. Параметры. Добавьте число параметров, которое требует sp.
  • command.ExecuteNonQuery

Существует множество примеров, первый Google возвращает это

Есть также небольшая ловушка, в которую вы можете попасть, если ваш SP является функцией, ваш параметр возвращаемого значения должен быть первым в коллекции параметров

17
задан Clint Miller 15 June 2009 в 12:13
поделиться

4 ответа

Если вам действительно нужно это сделать, используйте экзистенциальный :

{-# LANGUAGE GADTs #-}


class IsShape a where
    draw :: a -> IO ()

data Rectangle = Rectangle Int Int

instance IsShape Rectangle where
    draw (Rectangle length width) = ...

data Circle = Circle Int Int

instance IsShape Circle where
    draw (Circle center radius) = ...

data Shape where
    Shape :: IsShape a => a -> Shape

shapes = [Shape (Circle 5 10), Shape (Circle 20 30), Shape (Rectangle 10 15)]

(я переименовал ваш класс, так как в противном случае будет конфликт имени с типом данных, и такое именование кажется более естественным.)

Преимущество этого решения перед другим ответом, включающим один тип данных с разными конструкторами, состоит в том, что оно открыто ; вы можете определять новые экземпляры IsShape где угодно. Преимущество другого ответа состоит в том, что он более «функциональный», а также в том, что закрытость в некоторых случаях может быть преимуществом, поскольку это означает, что клиенты точно знают, чего ожидать.

22
ответ дан 30 November 2019 в 10:59
поделиться

Рассмотрите возможность использования одного типа вместо отдельных типов и класса типов.

data Shape = Rectangle Int Int
           | Circle Int Int

draw (Rectangle length width) = ...
draw (Circle center radius)   = ...

shapes = [Circle 5 10, Circle 20 30, Rectangle 10 15]
13
ответ дан 30 November 2019 в 10:59
поделиться

Как сказал Ганеш, вы действительно можете использовать GADT для большей безопасности типов. Но если вы этого не хотите (или не нуждаетесь), вот мой вариант:

Как вы уже знаете, все элементы списка должны быть одного типа. Не очень полезно иметь список элементов разных типов, потому что тогда вы выбрасываете информацию о своем типе.

Однако в этом случае, поскольку вы хотите выбросить информацию о типе (вас просто интересует рисованная часть значения), вы бы предложили изменить тип ваших значений на что-то, что можно просто рисовать.

type Drawable = IO ()

shapes :: [Drawable]
shapes = [draw (Circle 5 10), draw (Circle 20 30), draw (Rectangle 10 15)]

Предположительно, ваш фактический Drawable будет чем-то более интересным, чем просто IO () (может быть, что-то вроде: MaxWidth -> IO () ).

А также, из-за ленивой оценки фактическое значение выиграло ' t рисоваться до тех пор, пока вы не зададите список с чем-то вроде sequence_ . Так что вам не нужно беспокоиться о побочных эффектах (но вы, вероятно, уже видели это по типу фигур ).


Для полноты (и включите мой комментарий в этот ответ): Это более общая реализация, полезная, если Shape имеет больше функций:

type MaxWith = Int

class Shape a where
    draw :: a -> MaxWidth -> IO ()
    size :: a -> Int

type ShapeResult = (MaxWidth -> IO (), Int)

shape :: (Shape a) => a -> ShapeResult
shape x = (draw x, size x)

shapes :: [ShapeResult]
shapes = [shape (Circle 5 10), shape (Circle 20 30), shape (Rectangle 10 15)]

Здесь функция shape преобразует значение Shape a в ShapeResult , просто вызывая все функции в классе Shape . Из-за лени ни одно из значений фактически не вычисляется, пока они вам не понадобятся.

Честно говоря, я не думаю, что на самом деле использовал бы такую ​​конструкцию. Я бы либо использовал метод Drawable , указанный выше, либо, если требуется более общее решение, использовать GADT. При этом это забавное упражнение.

5
ответ дан 30 November 2019 в 10:59
поделиться

Один из способов сделать это - использовать vtables:

data Shape = Shape {
  draw :: IO (),
  etc :: ...
}

rectangle :: Int -> Int -> Shape
rectangle len width = Shape {
  draw = ...,
  etc = ...
}

circle :: Int -> Int -> Shape
circle center radius = Shape {
  draw = ...,
  etc = ...
}
5
ответ дан 30 November 2019 в 10:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: