TL;DR
Если я правильно понимаю, у Haskell нет подтипов так, как это делает F #. Таким образом, я ожидаю, что у него нет шаблона тестового типа для сопоставления, например F #. Имеет ли он какие-либо аналогичные конструкции, которые можно использовать для метапрограммирования?
Пример из практики
У меня есть проект F #, в котором у меня есть развязанные модули, которые говорят через механизм обмена сообщениями. Недавно я задавался вопросом, как будет выглядеть этот код, или если бы это было возможно написать так, если бы я должен был перенести его в Haskell.
Основная идея такова. Сообщение - это тип, который наследуется от интерфейса сообщения:
type Message = interface end
Обработчик - это функция, которая принимает определенный подтип Message
и возвращает a Message
:
type Handle<'TMsg when 'TMsg :> Message> = 'TMsg -> Message
Существует Bus
с методом publish
, который распространяет сообщение на свои внутренние каналы. Существует один тип Channel<'TMsg>
для каждого типа сообщений, и они динамически добавляются при регистрации обработчика. Шина публикует все сообщения для всех каналов, и если она неправильного типа, канал просто возвращает пустую последовательность:
type Channel<'TIn when 'TIn :> Message>(...) = ...
interface Channel with
member x.publish (message : Message) =
match message with
| :? 'TIn as msg ->
Seq.map (fun handle -> handle msg) _handlers
|> Seq.filter (fun msg -> msg <> noMessage)
| _ -> Seq.empty
В конечном итоге то, что я здесь делаю, - это динамическое метапрограммирование, которое позволяет мне иметь строго типизированные сообщения, которые по-прежнему проходят через один и тот же механизм посередине. Я не такой, как Haskell, как F #, и я не могу понять, как это сделать в Haskell.
Я прав, что у Haskell нет конструкции match... with... :?... as...
? Имеет ли он подобную конструкцию или другой подход к подобному метапрограммированию, с которым вы можете решить эту проблему? Есть какой-то механизм box/unbox?