一个简单的模型可能如下:
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeOperators #-}
module Taint ( (:+), srand, BadRandom, Unbounded, Tainted (), (<+>)) where
import Control.Applicative
import Control.Monad.Identity
data a :+ b
data BadRandom
data Unbounded
newtype Tainted taint a = Tainted { clean :: Identity a }
deriving ( Functor, Applicative, Monad )
(<+>) :: Tainted t1 (a -> b) -> Tainted t2 a -> Tainted (t1 :+ t2) b
Tainted (Identity f) <+> Tainted (Identity x) = Tainted (Identity (f x))
srand :: IO (Tainted BadRandom Int)
srand = undefined
由于clean
未导出,因此用户srand
无法删除Tainted
标签。此外,您可以使用“伪Applicative
”应用功能(<+>)
来合并污点。Monad
我们也可以很容易地为“伪”接口生成一个类似的组合器:
(>>-) :: Tainted t1 a -> (a -> Tainted t2 b) -> Tainted (t1 :+ t2) b
Tainted (Identity a) >>- f = let Tainted (Identity b) = f a in Tainted (Identity b)