Haskell 是否可以使用递归求和类型,每个';级别';有独特的价值?
我想知道是否有可能(我猜是:))有一个递归和类型,其中我们在每个级别上都有一个X类型的值,但不知何故,我们限制自己在每个递归级别上都有不同的X值 例如,如果我有Haskell 是否可以使用递归求和类型,每个';级别';有独特的价值?,haskell,Haskell,我想知道是否有可能(我猜是:))有一个递归和类型,其中我们在每个级别上都有一个X类型的值,但不知何故,我们限制自己在每个递归级别上都有不同的X值 例如,如果我有 data MachineType=工人|飞行员|挖掘机|观察者|攻击者 数据机=单机类型|多机类型机器 类型系统允许我构造以下类型的机器: Multi-Worker(多个Worker(单个Worker)) 但我希望对其进行限制,以便只允许使用不同的MachineType-s 有没有办法在类型系统中对其进行编码 你可以给我指出正确的方
data MachineType=工人|飞行员|挖掘机|观察者|攻击者
数据机=单机类型|多机类型机器
类型系统允许我构造以下类型的机器:
Multi-Worker(多个Worker(单个Worker))
但我希望对其进行限制,以便只允许使用不同的MachineType-s
有没有办法在类型系统中对其进行编码
你可以给我指出正确的方向,因为我不知道用谷歌搜索什么:)(haskell集合像递归和类型?一个解决方案是指定不能用重复的
机器类型扩展机器。为此,我们首先需要MachineType
的类型:
{-# language TypeInType, GADTs, TypeOperators, ConstraintKinds,
UndecidableInstances, TypeFamilies #-}
import Data.Kind
import GHC.TypeLits
data MachineType = Worker | Flyer | Digger | Observer | Attacker
data SMachineType t where
SWorker :: SMachineType Worker
SFlyer :: SMachineType Flyer
SDigger :: SMachineType Digger
SObserver :: SMachineType Observer
SAttacker :: SMachineType Attacker
然后,我们指定一个约束,如果MachineType
s的列表中不包含某个内容,则该约束是可满足的,否则抛出:
以下定义已推断出类型机器“[”传单、“挖掘机”、“工人]
:
m1 = Multi SFlyer (Multi SDigger (Single SWorker))
以下定义引发类型错误:
m2 = Multi SFlyer (Multi SFlyer (Single SWorker))
错误消息为:
Notes.hs:30:6: error: …
• Duplicate MachineTypes are not allowed in Machines
Can't add 'Flyer to '[ 'Flyer, 'Worker]
...
看来我被打败了!作为对安德拉斯答案的补充,我提出了一个类似的版本,但使用了每种机器类型唯一性的价值级证明
在实际用例中,这可能不太符合人体工程学,但它确实具有某种“与证明相关的数学”的魅力(或者我欺骗自己去思考!)
您可以使用phantom类型参数,该参数是MachineType的类型级别列表,并使机器成为GADT,其中构造函数需要证明列表不包含给定类型的机器already@sara的注释当然是一种方法,但是仅仅使用和执行newtype Machine=Machine不是更简单吗{getMachines::Set MachineType}
?谢谢你的回答!我将研究HLists和GADT,看看它们是如何工作的。我也在考虑集合,但想知道这是否可以在“上面”一级完成。我想编码的是类似于“X加上Y”的东西,集合可以解释为“X加上Y”和“Y加上X”。模式为m在Atch中,我首先需要处理“主”对象,即X,如果我愿意,然后向下递归到它的其他组件。但如果我不知道其他解决方案是如何工作的,这绝对是一个选项:)感谢沿途提供的示例和解释。它已经工作了,现在我将花一些时间阅读您发布的教程我想了解一下单身人士图书馆,了解它为什么会起作用。干杯!
m2 = Multi SFlyer (Multi SFlyer (Single SWorker))
Notes.hs:30:6: error: …
• Duplicate MachineTypes are not allowed in Machines
Can't add 'Flyer to '[ 'Flyer, 'Worker]
...
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TypeFamilies #-}
import Prelude
import Data.Kind (Type)
import Data.Void (Void)
import Data.Proxy (Proxy(..))
data MachineType
= Worker
| Flyer
| Digger
| Observer
| Attacker
deriving (Show, Eq)
data In xs x where
Here :: forall k (xs :: [k]) (x :: k)
. In (x ': xs) x
There :: forall k (xs :: [k]) (x :: k) (y :: k)
. In xs x -> In (y ': xs) x
type family Not a where
Not a = (a -> Void)
data Machine :: [MachineType] -> Type where
Single :: forall (t :: MachineType) (proxy :: MachineType -> Type)
. proxy t -> Machine '[t]
Multi :: forall (t :: MachineType) (ts :: [MachineType]) (proxy :: MachineType -> Type)
. Not (In ts t) -> proxy t -> Machine ts -> Machine (t ': ts)
simpleMachine :: Machine '[ 'Worker ]
simpleMachine = Single Proxy
multiMachine :: Machine '[ 'Flyer, 'Attacker ]
multiMachine = Multi p (Proxy @'Flyer) $ Single (Proxy @'Attacker)
where
p :: Not (In '[ 'Attacker ] 'Flyer)
p = \case
There l -> case l of