Functions that work with only one type constructor

I am writing lib for message queues. Queues can be either Director Topic. Directqueues have a static key binding, and queues Topiccan have dynamic.

I want to write a function publishthat only works in queues Direct. It works:

{-# LANGUAGE DataKinds #-}

type Name = Text
type DirectKey = Text
type TopicKey = [Text]

data QueueType
  = Direct DirectKey
  | Topic TopicKey

data Queue (kind :: a -> QueueType)
  = Queue Name QueueType

This requires two separate constructors.

directQueue :: Name -> DirectKey -> Queue 'Direct

topicQueue :: Name -> TopicKey -> Queue 'Topic

But when I am going to write a publication, there is an additional template that I need to map, which should be impossible

publish :: Queue 'Direct -> IO ()
publish (Queue name (Direct key)) =
   doSomething name key
publish _ =
   error "should be impossible to get here"

, ? Direct Text, Topic [Text]. , ?

+4
2

Queue

data Queue a = Queue Name a

Queue DirectKey Queue TopicKey? publish :: Queue DirectKey -> IO ().

, , , Queue, , , DirectKey TopicKey , ,

commonFunction :: MyTypeclass a => Queue a -> IO ()

, typeclass

class MyTypeclass a where
    commonFunction :: Queue a -> IO ()
+6

( PolyKinds), , , , , , , , .

, GADT ( , , , , , @danidiaz).

. :

data Queue (kind :: a -> QueueType)
  = Queue Name QueueType

Queue ( kind), Queue , QueueType . Queue Name QueueType kind; phantom. QueueType , kind Queue kind .

, GHC , publish, Queue 'Direct; , .

GADT , , . , ( ), .

, Queue 'Direct , Queue 'Topic , Queue a.

QueueType GADT, . , , ( PolyKinds), ( !) , . :

data QueueType
  = Direct
  | Topic

data QueueData (a :: QueueType)
  where DirectData :: DirectKey -> QueueData 'Direct
        TopicData :: TopicKey -> QueueData 'Topic

, QueueType DataKinds ( - ). QueueData, QueueType. DirectKey a QueueData 'Direct, a TopicKey a QueueData 'Topic.

Queue, :

data Queue (a :: QueueType)
  = Queue Name (QueueData a)

, (, QueueData), Queue a:

getName :: Queue a -> Text
getName (Queue name _) = name

Queue a, , , :

getKeyText :: Queue a -> Text
getKeyText (Queue _ (DirectData key)) = key
getKeyText (Queue _ (TopicData keys)) = mconcat keys

, , Queue 'Direct, publish, GHC , DirectData QueueData. , , OP, , TopicData .

:

{-# LANGUAGE DataKinds, GADTs, KindSignatures #-}

import Data.Text (Text)

type Name = Text
type DirectKey = Text
type TopicKey = [Text]

data QueueType
  = Direct
  | Topic

data QueueData (a :: QueueType)
  where DirectData :: DirectKey -> QueueData 'Direct
        TopicData :: TopicKey -> QueueData 'Topic

data Queue (a :: QueueType)
  = Queue Name (QueueData a)


getName :: Queue a -> Text
getName (Queue name _) = name

getKeyText :: Queue a -> Text
getKeyText (Queue _ (DirectData key)) = key
getKeyText (Queue _ (TopicData keys)) = mconcat keys

publish :: Queue 'Direct -> IO ()
publish (Queue name (DirectData key))
  = doSomething name key
  where doSomething = undefined
+2

Source: https://habr.com/ru/post/1657549/


All Articles