如何从具有类型相等约束的 Scott 编码的 GADT 中获取值?
How to get the value from a Scott encoded GADT with type equality constraints?
我正在阅读 the Rank-N-Types section of 24 days of GHC Extensions 并遇到了以下 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
虽然 unSome
在其类型变量中是多态的,但我们可以向编译器证明,例如在 SomeInt
的情况下,给定值加三是安全的。作者将这种类型称为细化。
现在我很好奇我是否可以对 Scrott 编码类型做同样的事情。幸运的是,有一个这种编码的例子。我们只需要打开 Rank-N-Types 和 Type-Families 扩展:
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE RankNTypes #-}
newtype SomeC a =
SomeC {
runSomeC ::
forall r.
((a ~ Int) => Int -> r) ->
((a ~ Char) => Char -> r) ->
(a -> r) ->
r
}
但是,文章中没有提供 unSome
。我不精通 Haskell 并且不知道如何使用 Scott 编码实现此功能。特别是类型等式约束(例如 (a ~ Int) =>
)让我很困惑。
感谢任何有关其他在线资源的帮助或信息。
您只需使用提供的函数来替换您的模式匹配,如:
{-# 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)
在 ghci 中:
> unSome (SomeC (\someInt someChar anything -> someInt 2))
5
我正在阅读 the Rank-N-Types section of 24 days of GHC Extensions 并遇到了以下 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
虽然 unSome
在其类型变量中是多态的,但我们可以向编译器证明,例如在 SomeInt
的情况下,给定值加三是安全的。作者将这种类型称为细化。
现在我很好奇我是否可以对 Scrott 编码类型做同样的事情。幸运的是,有一个这种编码的例子。我们只需要打开 Rank-N-Types 和 Type-Families 扩展:
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE RankNTypes #-}
newtype SomeC a =
SomeC {
runSomeC ::
forall r.
((a ~ Int) => Int -> r) ->
((a ~ Char) => Char -> r) ->
(a -> r) ->
r
}
但是,文章中没有提供 unSome
。我不精通 Haskell 并且不知道如何使用 Scott 编码实现此功能。特别是类型等式约束(例如 (a ~ Int) =>
)让我很困惑。
感谢任何有关其他在线资源的帮助或信息。
您只需使用提供的函数来替换您的模式匹配,如:
{-# 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)
在 ghci 中:
> unSome (SomeC (\someInt someChar anything -> someInt 2))
5