首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Kotlin不变型的Haskell等价

Kotlin不变型的Haskell等价
EN

Stack Overflow用户
提问于 2022-07-16 16:01:16
回答 1查看 228关注 0票数 1

在科特林,我能做到

代码语言:javascript
运行
复制
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
}

现在我有了不变类型DangerousBox<Substance.Uranus>, DangerousBox<Substance.Mercury>等等,所以上面的示例不会编译。

在哈斯克尔是怎么做到的?

理想情况下,我想要类型

代码语言:javascript
运行
复制
uranus :: DangerousBox Uranus
uranus = DangerousBox Mercury

这个样本也不合适。

我试图通过以下方式实现这一目标:

  1. 模约束我有模块
代码语言:javascript
运行
复制
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

模块的客户端只能使用dangerousBox,但是这里我有一个关于内容的jeneric:

代码语言:javascript
运行
复制
uranus :: VDangerousBox Substance
uranus = dangerousBox Uranus
  1. 数据种类
代码语言:javascript
运行
复制
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 -}

但在这种情况下,下面的情况将编译:

代码语言:javascript
运行
复制
mercury :: DangerousBox Mercury
mercury = DangerousBox Ammonia

我知道我收到了相当于

代码语言:javascript
运行
复制
data Box<T : Substance>(val value: Substance)

就科特林的泛型而言。

这不是真正的案例,它只是“学术”的兴趣。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-16 16:54:28

考虑到特定的物质选择,框中不包含任何其他信息(至少在Kotlin代码中是这样),所以我首先考虑完全忽略它:

代码语言:javascript
运行
复制
import Data.Kind (Type)  -- preferred version instead of the old *

data DangerousBox :: Substance -> Type where
  DangerousBox :: DangerousBox a

uranus :: DangerousBox Uranus
uranus = DangerousBox

那么mercury = DangerousBox Ammonia问题甚至不会出现,因为DangerousBox值构造函数不带任何参数。

如果出于某种原因,您确实需要一个表示标记类型的实际值,那么这不应该是标记本身为Type-value,因为在该视图中,UranusMercuryAmmonia都是相同的类型。相反,您应该使用通常称为这些类型的单例。您可以让它们自动生成,也可以手动定义它们:

代码语言:javascript
运行
复制
data SubstanceSing :: Substance -> Type where
  UranusS :: SubstanceSing 'Uranus
  MercuryS :: SubstanceSing 'Mercury
  AmmoniaS :: SubstanceSing 'Ammonia

现在,UranusS对应于在值级别上出现的Kotlin Substance.Uranus。你的盒子类型就变成了

代码语言:javascript
运行
复制
data DangerousBox :: Substance -> Type where
  DangerousBox :: SubstanceSing a -> DangerousBox a
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73005712

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档