Tru*_*arg 1 haskell functional-programming kotlin data-kinds jenetics
在科特林我可以做
sealed class Substance {
object Uranus : Substance()
object Mercury: Substance()
object Ammonia : Substance()
}
data class DangerousBox<T : Substance>(val item: T)
fun main() {
val uranus = DangerousBox<Substance.Uranus>(Substance.Uranus)
val mercury: DangerousBox<Substance.Mercury> = uranus
}
Run Code Online (Sandbox Code Playgroud)
现在我有不变的类型DangerousBox<Substance.Uranus>, DangerousBox<Substance.Mercury>等,所以上面的示例将无法编译。
如何在 Haskell 中做到这一点?
理想情况下我想要类型
uranus :: DangerousBox Uranus
uranus = DangerousBox Mercury
Run Code Online (Sandbox Code Playgroud)
这个样本也不能符合。
我尝试通过以下方式来实现:
module Sample.Types.Boxes
( Substance(..)
, dangerousBox
, VDangerousBox {- no Con-}
) where
data Substance
= Uranus
| Mercury
| Ammonia
deriving (Show)
data VDangerousBox a =
VDangerousBox Substance
deriving (Show)
dangerousBox :: Substance -> VDangerousBox Substance
dangerousBox a = VDangerousBox a
Run Code Online (Sandbox Code Playgroud)
模块的客户端只能使用危险框,但这里我有与物质相关的 jeneric:
uranus :: VDangerousBox Substance
uranus = dangerousBox Uranus
Run Code Online (Sandbox Code Playgroud)
data DangerousBox :: Substance -> * where
DangerousBox :: Substance -> DangerousBox a
uranus :: DangerousBox Uranus
uranus = DangerousBox Uranus
mercury :: DangerousBox Mercury
mercury = uranus {- it's ok, it dosn't compile -}
Run Code Online (Sandbox Code Playgroud)
但在这种情况下,以下情况将编译:
mercury :: DangerousBox Mercury
mercury = DangerousBox Ammonia
Run Code Online (Sandbox Code Playgroud)
我了解我已收到同等金额
data Box<T : Substance>(val value: Substance)
Run Code Online (Sandbox Code Playgroud)
就 Kotlin 泛型而言。
这不是真实的案例,只是出于“学术”兴趣。
因为,给定特定的物质选择,框中没有任何其他信息包含(至少在您的 Kotlin 代码中),所以我首先考虑完全忽略它:
import Data.Kind (Type) -- preferred version instead of the old *
data DangerousBox :: Substance -> Type where
DangerousBox :: DangerousBox a
uranus :: DangerousBox Uranus
uranus = DangerousBox
Run Code Online (Sandbox Code Playgroud)
那么mercury = DangerousBox Ammonia问题就不会出现,因为DangerousBox值构造函数不接受任何参数。
如果由于某种原因您确实需要一个代表标记类型的实际值,那么这不应该是标记本身作为值Type,因为在该视图中Uranus、Mercury和Ammonia都是相同的类型。相反,您应该使用通常所说的这些类型的单例。您可以自动生成它们,或手动定义它们:
data SubstanceSing :: Substance -> Type where
UranusS :: SubstanceSing 'Uranus
MercuryS :: SubstanceSing 'Mercury
AmmoniaS :: SubstanceSing 'Ammonia
Run Code Online (Sandbox Code Playgroud)
现在出现在值级别时UranusS对应于您的 Kotlin 。Substance.Uranus然后你的盒子类型就变成了
data DangerousBox :: Substance -> Type where
DangerousBox :: SubstanceSing a -> DangerousBox a
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
308 次 |
| 最近记录: |