How can I cause a type error in Haskell?

Suppose I have a type

data F a = A a | B

I implement the function f :: F a -> F a -> F aas follows:

f (A x) B = A x
f B (A _) = B
f (A _) (A x) = A x

However, such a thing as f B Bis logically impossible, so I want:

f B B = GENERATE_HASKELL_COMPILE_ERROR

which doesn't work of course. Omitting a definition or using f B B = undefinedit is not a solution because it throws an exception at runtime. I would like to get a compilation type error.

The compiler has all the information, it should be able to output, I made a logical mistake. If I declare let z = f (f B (A 1)) B, it should be an immediate compile-time error, and not some kind of runtime exception that may be hidden in my code for many years.

, , , , - Haskell.


EDIT: , , , Haskell (). , . David Young , . , .

+4
3

, , , (, - , , ).

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

import Data.Constraint

data AType
data BType

data F x y where
  A :: a -> F AType a
  B ::      F BType a

type family ValidCombo x y :: Constraint where
  ValidCombo BType ty2 = ty2 ~ AType
  ValidCombo ty1   ty2 = ()

f :: ValidCombo ty1 ty2 => F ty1 a -> F ty2 a -> F ty1 a
f (A x) B     = A x
f B     (A _) = B
f (A _) (A x) = A x

f B B = ..., f B B. let z = f (f B (A 1)) B ( ).

, , F. ( , ). (AType BType) phantom F.

ValidCombo ( , , Haskell, ). () - , ( , , ). a ~ b a b (~ ) , . , ( F), :

data Tag = ATag | BTag
  deriving Eq

getTag :: F a -> Tag
getTag (A _) = ATag
getTag B     = BTag

validCombo :: F a -> F a -> Bool
validCombo B tag2 = (getTag tag2) == ATag
validCombo _ _    = True

( , " " .)

DataKinds, , F AType BType, ( ).

, , Maybe, @DirkyJerky, - (- ).

Haskell ( , , , ), , .

+9

, " Haskell" , Maybe F

f f :: F a -> F a -> Maybe (F a), catch:

f (A x) B = Just $ A x
f B (A _) = Just $ B
f (A _) (A x) = Just $ A x
f B B = Nothing

.

, , , f, B? ? .

+4

, , .

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

data F x a where
  A :: a -> F 'True a
  B :: F 'False a

f
  :: ((x || y) ~ 'True)
  => F x a
  -> F y a
  -> F (x || Not y) a

f (A a) B = A a
f B (A _) = B
f (A _) (A a) = A a

----

type family Not a where
  Not 'True = 'False
  Not 'False = 'True

type family a || b where
  'True || 'True = 'True  -- *
  'True || b = 'True
  a || 'True = 'True
  a || b = 'False

* , .

:

  • B, A,
  • f B B ( " " )
  • f B B, - f (f B (A 1)) B
+2

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


All Articles