我想知道是否有可能(我想是:))具有递归和类型,其中我们在每个级别上都有X类型的值,但是以某种方式限制了我们自己,在每个级别的递归上我们都有不同的值X?
例如,如果我有
data MachineType = Worker | Flyer | Digger | Observer | Attacker
data Machine = Single MachineType | Multi MachineType Machine
类型系统允许我构造以下类型的计算机:
Multi Worker (Multi Worker (Single Worker))
但我希望对此加以限制,以便只允许使用不同的MachineType。
有没有办法在类型系统中对此进行编码?
您可以为我指明正确的方向,因为我有点不了解google :)(类似于haskell集的递归和类型吗?)
答案 0 :(得分:10)
一种解决方案是指定不能用重复的$result_array = mysqli_query($connect,"SELECT * FROM tbl_customer, categories WHERE tbl_customer.category_QA = categories.id ORDER BY Category ASC");
$checkCategory = '';
while($data = mysqli_fetch_array($result_array)){
if ($checkCategory != $data["Category"]){
echo $data["Category"]; //display once for every new category
$checkCategory = $data["Category"];
}
echo $data["productName"];
}
扩展Machine
。为此,我们首先需要为MachineType
使用singleton类型:
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
列表中未包含某些内容,则抛出约束,否则抛出custom type error:
MachineType
然后,将type family NotElem (x :: MachineType) (xs :: [MachineType]) :: Constraint where
NotElem x '[] = ()
NotElem x (x ': xs) = TypeError
(Text "Duplicate MachineTypes are not allowed in Machines" :$$:
(Text "Can't add " :<>: ShowType x :<>: Text " to "
:<>: ShowType (x ': xs)))
NotElem x (y ': xs) = NotElem x xs
作为GADT给出,并以Machine
的列表为索引:
MachineType
以下定义推断类型为data Machine (ts :: [MachineType]) where
Single :: SMachineType t -> Machine '[ t ]
Multi :: NotElem t ts => SMachineType t -> Machine ts -> Machine (t ': ts)
:
Machine '[ 'Flyer, 'Digger, 'Worker]
以下定义引发类型错误:
m1 = Multi SFlyer (Multi SDigger (Single SWorker))
错误消息为:
m2 = Multi SFlyer (Multi SFlyer (Single SWorker))
答案 1 :(得分:2)
看来我被殴打了!作为对安德拉斯的回答的补充,我想出了一个类似的版本,但是使用了每种机器类型的唯一性的价值水平证明。
这在实际用例中可能不太符合人体工程学,但是它确实具有一定的“证明相关数学”的魅力(或者,所以我自欺欺人!)
{-# 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