加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

将Scala类型示例转换为Haskell

发布时间:2020-12-16 19:02:18 所属栏目:安全 来源:网络整理
导读:我在 Scala文章中发现了一个非常有趣的例子,我想知道如何在Haskell中进行编码. trait Statustrait Open extends Statustrait Closed extends Statustrait Door[S : Status]object Door { def apply[S : Status] = new Door[S] {} def open[S : Closed](d: Do
我在 Scala文章中发现了一个非常有趣的例子,我想知道如何在Haskell中进行编码.

trait Status
trait Open extends Status
trait Closed extends Status

trait Door[S <: Status]
object Door {
  def apply[S <: Status] = new Door[S] {}

  def open[S <: Closed](d: Door[S]) = Door[Open]
  def close[S <: Open](d: Door[S]) = Door[Closed]
}

val closedDoor = Door[Closed]
val openDoor = Door.open(closedDoor)
val closedAgainDoor = Door.close(openDoor)

//val closedClosedDoor = Door.close(closedDoor) // fails to compile
//val openOpenDoor = Door.open(openDoor) // fails to compile

该样本在类型级别进行编码,您只能打开一个关闭的门,并且只关闭一个打开的门.我的第一次尝试只是使用简单的数据类型,但不能按照预期的方式工作:

data Status = Open | Closed deriving (Show)
data Door = Door Status deriving (Show)

open :: Door -> Door
open (Door Closed) = Door Open

close :: Door -> Door
close (Door Open) = Door Closed

main = do
  let closedDoor = (Door Closed)
  let openDoor = open closedDoor
  let closedAgainDoor = close openDoor
  let closeClosedDoor = close closedDoor
  let openOpenedDoor = open openDoor
  print closedAgainDoor

这实际上是编译(除非我尝试打印closeClosedDoor或openOpenedDoor,然后在功能打开中抱怨非穷尽的模式,这是显而易见的)

所以我试图弄清楚,我们的类型家庭的GADT是否可以完成这个任务,但是我还不能掌握如何.

有任何想法吗?

解决方法

除了bheklilr的答案之外,您可以使用一些类型扩展来更接近Scala示例,并排除非感性类型,例如

Door String

使用DataKinds,您可以有效地禁止幻像类型作为状态.

{-# LANGUAGE DataKinds #-}

data Door (status :: Status) = Door
data Status = Open | Closed

open :: Door Closed -> Door Open
open _ = Door

close :: Door Open -> Door Closed
close _ = Door

那么,对于类型的家庭,我们甚至可以定义“切换”门的意义

{-# LANGUAGE TypeFamilies #-}

type family Toggle (s :: Status) where
  Toggle Open = Closed
  Toggle Closed = Open

toggle :: Door s -> Door (Toggle s)
toggle Door = Door

作为一个闭幕式,使用GADT for Door可能更好 – 只是因为您有两个不同的构造函数名称.我个人认为这样看起来更好

{-# LANGUAGE GADTs,DataKinds,TypeFamilies #-}

data Door (status :: Status) where
  OpenDoor :: Door Open
  ClosedDoor :: Door Closed

open :: Door Closed -> Door Open
open _ = OpenDoor

close :: Door Open -> Door Closed
close _ = ClosedDoor

toggle :: Door s -> Door (Toggle s)
toggle OpenDoor = ClosedDoor
toggle ClosedDoor = OpenDoor

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读