Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Here's some code:

  {-# LANGUAGE
          TypeFamilies,
          MultiParamTypeClasses,
          FlexibleInstances #-}

  data True = T
  data False = F

  class LogicOr a b where
    type Or a b
    typeOr :: a -> b -> Or a b
  instance LogicOr True b where
    type Or True b = True
    typeOr T b = T
  instance LogicOr a True where
    type Or a True = True
    typeOr b T = T
  instance LogicOr False False where
    type Or False False = False
    typeOr F F = F

  class Decide tf a b where
    type If tf a b
    nonFunctionalIf :: tf -> a -> b -> If tf a b
  instance Decide True a b where
    type If True a b = a
    nonFunctionalIf T a b = a
  instance Decide False a b where
    type If False a b = b
    nonFunctionalIf F a b = b

  whatIsMyType tf1 tf2 a b = nonFunctionalIf (typeOr tf1 tf2) a b
If we load this into ghci, we have the following example:

  *Main> :t whatIsMyType F F 2 "foo"
  whatIsMyType F F 2 "foo" :: (Num t) => If (Or False False) t [Char]
  *Main> :t whatIsMyType F F 2 "foo" :: String
  whatIsMyType F F 2 "foo" :: String :: String
In the first :t, ghci lazily (though correctly) gives us the type of whatIsMyType. In the second example, where we provide an explicit type annotation, ghci is able to (correctly) conclude that our annotation was correct by evaluating the various type functions it had given us before.


Thanks. I can reproduce your example.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: