简体   繁体   中英

How to get the value from a Scott encoded GADT with type equality constraints?

I am reading the Rank-N-Types section of 24 days of GHC Extensions and came across the following GADT:

{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}

import Data.Char

data Some :: * -> * where
    SomeInt  :: Int -> Some Int
    SomeChar :: Char -> Some Char
    Anything :: a -> Some a

unSome :: Some a -> a
unSome (SomeInt x) = x + 3
unSome (SomeChar c) = toLower c
unSome (Anything x) = x

unSome (someInt 2) -- 5

Although unSome is polymorphic in its type variables one can give the compiler proof that in the SomeInt case for instance, it is safe to add three to the given value. The author calls this type refinement.

Now I was curious whether I can do the same with a Scrott encoded type. Fortunately, there is an example of such encoding. We merely need the Rank-N-Types and Type-Families extensions turned on:

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE RankNTypes #-}

newtype SomeC a =
    SomeC {
      runSomeC ::
          forall r.
          ((a ~ Int) => Int -> r) ->
          ((a ~ Char) => Char -> r) ->
          (a -> r) ->
          r
    }

However, unSome isn't provided in the article. I am not well-versed in Haskell and don't have a clue how to implement this function with Scott encoding. Especially the type equality constraints (eg (a ~ Int) => ) confuse me.

Any help or information on other online sources are appreciated.

You just use the provided function to replace your pattern match, as in:

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE RankNTypes #-}

import Data.Char

newtype SomeC a =
    SomeC {
      runSomeC ::
          forall r.
          ((a ~ Int) => Int -> r) ->
          ((a ~ Char) => Char -> r) ->
          (a -> r) ->
          r
    }

unSome :: SomeC a -> a
unSome (SomeC f) = f (\x -> x+3) (\c -> toLower c) (\x -> x)

In ghci:

> unSome (SomeC (\someInt someChar anything -> someInt 2))
5

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM