How can I restrict types based on input values ​​in Haskell?

I am new to Haskell. Sorry if this question has an obvious answer.

I have

data Tmp = Foo Int
         | Bar Int
         | Baz Int

and

data Test = A Tmp Tmp

The constructor A Tmp Tmpcan accept any constructor for Tmp, with the exception of A (Baz i) (Baz j)where iand jare arbitrary Ints. Is there a way that I can limit the second Tmpto A Tmp Tmpfrom Baz, if the first is Tmpalready Baz?

+4
source share
1 answer

The answer depends on how you want your restriction to be executed: at run time or at compile time.

, (, makeA), . , , , . makeA, A , , , .

:

module Test (Tmp (Foo, Bar, Baz), Test (), makeA) where
  data Tmp
     = Foo Int
     | Bar Int
     | Baz Int

  data Test = A Tmp Tmp

  makeA :: Tmp -> Tmp -> Tmp
  makeA (Baz _) (Baz _) = error "makeA: two baz problem"
  makeA tmp1 tmp2 = A tmp1 tmp2

, . , .

, - . , , Foo Bar, , Baz. Tmp, , Tmp , - . "Bazness" Tmp .

Bazness Tmp :

data TmpNotBaz
  = Foo Int
  | Bar Int

data Tmp
  = NotBaz TmpNotBaz
  | Baz Int

, TmpNotBaz Baz, Tmp Baz. , Haskell. , NotBaz . , - " A Baz, ". A:

data Test
  = A1 TmpNotBaz Tmp
  | A2 Tmp TmpNotBaz

, , A1 A2 , A (Baz ...) (Baz ...) , . , , , , A (Foo 1) (Foo 2): A1 (Foo 1) (NotBaz (Foo 2)) A2 (NotBaz (Foo 1)) (Foo 2) .

, , , .

Bazness , Tmp , , , Haskell. , , , "" Haskell. , :

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

data Bazness = IsBaz | NotBaz

data BothBazOrNot = BothBaz | NotBothBaz

type family AreBothBaz (b1 :: Bazness) (b2 :: Bazness) :: BothBazOrNot where
  AreBothBaz 'IsBaz 'IsBaz = 'BothBaz
  AreBothBaz _ _ = 'NotBothBaz

data Tmp (b :: Bazness) :: * where
  Foo :: Int -> Tmp 'NotBaz
  Bar :: Int -> Tmp 'NotBaz
  Baz :: Int -> Tmp 'IsBaz

data Test where
  A :: AreBothBaz b1 b2 ~ 'NotBothBaz => Tmp b1 -> Tmp b2 -> Test

, Foo, Bar Baz , -, IsBaz NotBaz. A b1 b2, NotBothBaz.

, :

  • A (Foo 1) (Bar 2)
  • A (Foo 1) (Baz 2)
  • A (Baz 1) (Bar 2)

A (Baz 1) (Baz 2), :

Couldn't match type 'BothBaz with 'NotBothBaz
    arising from a use of A
 In the expression: A (Baz 1) (Baz 2)

, , A BothBaz, A, NotBothBaz, , BothBaz NotBothBaz.

+13

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


All Articles