Erè*_*èbe 0 polymorphism haskell higher-rank-types
haskell中是否有一种方法可以将类型信息/向下转换为多态值?
在示例中,我有一个盒装类型T,它可以包含一个Int或一个Char我想写一个函数来提取这个值而不知道它是哪个类型.
{#- LANGUAGE RankNTypes -#}
data T = I Int | C Char
-- This is not working because GHC cannot bind "a"
-- with specific type Int and Char at the same time.
-- I just want a polymorphic value back ;(
getValue :: T -> (forall a. a)
getValue (I val) = val
getValue (C val) = val
-- This on the other hand works, because the function
-- is local to the pattern matching expression
onValue :: T -> (forall a. a -> a) -> T
onValue (I val) f = I $ f val
onValue (C val) f = C $ f val
Run Code Online (Sandbox Code Playgroud)
有没有办法编写一个函数,可以提取这个值而不必在最后强制类型?
像第一个一样的getValue函数?
如果不够清楚,请告诉我.
所以问题是愚蠢的,因为AndrewC(在评论中)和YellPika指出.无限型没有意义.
J. Abrahamson提供了我正在寻找的解释,所以我把他的答案作为解决方案.
PS:我不想使用GADT,因为我不想每次都使用新类型.
你可能想要的不是返回一个值,(forall a . a)因为它在几个方面是错误的.首先,你没有任何价值,而只是两个中的一个.对于二,这样的类型不能存在于行为良好的程序中:它对应于无限循环和异常的类型,例如底部.
最后,这种类型允许拥有它的人做出选择以更具体地实例化它.因为你将它交给你的函数的调用者,这意味着他们可以选择你拥有的Int或Char中的哪一个.显然这没有意义.
相反,你最想要的是向你的功能用户提出要求:"无论这种类型是什么,你都必须工作".
foo :: (forall a . a -> r) -> (T -> r)
foo f (I i) = f i
foo f (C c) = f c
Run Code Online (Sandbox Code Playgroud)
您会发现此功能与以下内容非常相似
bar :: r -> T -> r
bar x (I _) = x
bar x (C _) = x
Run Code Online (Sandbox Code Playgroud)
换句话说,如果你强迫你的函数的使用者忽略所有类型信息,那么,实际上什么都没有留下:例如一个常数函数.
你可以使用GADTs:
{-# LANGUAGE GADTs #-}
data T a where
I :: Int -> T Int
C :: Char -> T Char
getValue :: T a -> a
getValue (I i) = i
getValue (C c) = c
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
100 次 |
| 最近记录: |