单子的相关性

时间:2013-12-13 15:56:17

标签: haskell

newtype Set a = Set [a]

包含列表的新类型集。     empty ::设置一个     empty =设置[]

sing :: a -> Set a
sing x = Set [x]

创建集合的功能。

memSet :: (Eq a) => a -> Set a -> Bool
memSet _ (Set []) = False
memSet x (Set xs)
    | elem x xs = True
    | otherwise = False

{-
makeSet :: (Eq a) => [a] -> Set a
makeSet [] = empty
makeset (x:xs) = union (sing x) (makeSet xs)
-- etc
-- we need the obvious stuff:

union        :: Set a -> Set a -> Set a
unionMult    :: [ Set a ] -> Set a
intersection :: Set a -> Set a -> Set a
subSet       :: Set a -> Set a -> Bool
mapSet       :: (a -> b) -> Set a -> Set b
mapset f (Set xs) = makeSet (map f xs)
-}

-- now making it a monad:
instance Monad Set where
   return = sing
   (Set x) >>= f =  unionMult (map f x)

验证

左侧身份:

return a >>= f ≡ f a

正确的身份:

 m >>= return ≡ m

相关性:

 (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)

左:

return x >>= f
(Set [x]) >>= f
unionMult (map f [x])
unionMult [ (f x) ] = f x

对:

(Set [xs]) >>= return
unionMult (map return [xs])
unionMult [ys]
Set [xs]

需要最后一个帮助。

3 个答案:

答案 0 :(得分:2)

unionConcat已在Data.Set中定义....具体来说,我将在此证明中使用以下定义

unionConcat = Data.Set.unions
return = Data.Set.fromList [a]

(我将在这里使用Data.Set中定义的其他函数,有些可能需要“Ord a”,大概这不会有问题)。

我还使用了以下属性

union x y = fromList (toList x ++ toList y)
concat . map (:[]) = id

第一个说明两个集合的联合可以通过获取集合中的项目列表,将它们连接起来然后删除重复来获得......这是从集合的定义中得出的

第二个属性只是声明concat和map(:[])是彼此的反转。从concat

的定义中也应该明显看出这一点
map (:[]) [a, b, c, ....] = [[a], [b], [c], ....]
concat [[a], [b], [c], ....] = [a, b, c, ....]

(为了真正完成这个证明,我必须证明这些属性来自(:[]),concat和union的Haskell定义,但这是我认为你想要的更多细节,以及实际定义可能会因版本而异,因此我们只需要假设这些函数的编写者遵循集合和连接应该如何工作的精神。)

(如果不明显,请记住猴子操作符(:[])将单个元素包装在括号中 - (:[])x = [x])。

由于“工会”只是“联合”的多重应用,而“联合”只是(++)的多重应用,第一个属性可以推广到

unions sets = fromList (concat $ map toLists sets)

现在为证明 -

y >>= return 
= unions $ map return (toList y)
= unions $ map (fromList . (:[])) (toList y)
= unions $ map fromList $ map (:[]) (toList y)
= unions $ map fromList $ map (:[]) $ toList y
= fromList $ concat $ map toList $ map fromList $ map (:[]) (toList y)
= fromList $ concat $ map (:[]) (toList y)
= fromList $ toList y
= y

QED


编辑 - 见下面的讨论,我犯了一个错误并且证明了错误的法律(噢,我应该刚读完问题的标题:)),所以我在下面添加正确的(关联性)。 / p>

两个证明相关性,我们需要使用两个属性....

property 1 - toList (x >>= f) = su (toList x >>=' toList . f)
property 2 - su (x >>=' f) = su (su x >>=' f)

其中su是对一个列表进行排序和统一,即 -

su [4,2,4,1] = [1,2,4], 

和>> ='是数组绑定运算符,

x >>=' f = concat . map f x 

第一个属性应该是显而易见的....它只是声明你可以用两种不同的方式得到x>> = f的结果,或者通过将f应用于集合x中的值并取得联合,或与相应列表中完全相同的值,并对值进行汇总。唯一的问题是您可能会在列表中获得重复值(该集合甚至不允许这样做),因此您应用右侧的su函数来规范化结果(请注意,toList也以相同的形式输出)。

第二个属性指出,如果您在绑定管道的末尾对结果进行排序/取消,您也可以在管道中更早地执行它而不更改答案。同样,这应该是显而易见的....添加/删除重复项或使用初始列表重新排序值只会添加/删除重复项或重新排序最终结果。但是我们要删除重复项并在最后重新排序,所以没关系。

(根据map / concat,toList等的定义,可以给出这两个属性的更严格的证据,但它会炸掉这个帖子的大小....我会假设每个人的直觉是足够强大并继续....)

使用这些,我现在可以向您展示证明。一般计划是使用数组绑定运算符的已知关联性,以及数组与集合的关系,以表明set绑定运算符也必须是关联的。

toList set1 == toList set2

意味着

set1 == set2

我可以证明

toList ((y >>= f) >>= g) = toList (y >>= (\x -> f x >>= g))

获得理想的结果。

toList ((y >>= f) >>= g)
su (toList (y >>= f) >>=' toList . g) --by property 1
su (su (toList y >>=' toList . f) >>=' toList . g) --by property 1
su ((toList y >>=' toList . f) >>=' toList . g) --by property 2
su (toList y >>=' (\x -> (toList . f) x >>=' toList . g)) --by the associativity of the array bind operator
su (toList y >>=' (\x -> su (toList (f x) >>=' toList . g))) --by property 2 and associativity of (.)
su (toList y >>=' (\x -> toList (f x >>= g))) --by property 1
su (toList y >>=' toList (\x -> f x >>= g)) --by associativity of (.)
su (su (toList y >>=' toList (\x -> f x >>= g))) --by property 2
su (toList (y >>= (\x -> f x >>= g))) --by property 1
toList (y >>= (\x -> f x >>= g)) --because toList is already sorted/uniqued

QED

答案 1 :(得分:2)

由于Set a只是newtype左右[a],我们可以直接使用[]。只要我们使用Set个实例,证据就会相似;我们将能够直接使用[]的构造函数(有些)。这很好,因为我们可以归纳地证明事物。

我们想要展示所有xs :: [a] xs >>= return == xs。我们先假设xs == []

[] >>= return
unionConcat (map return [])
unionConcat []
[]

如果没有定义unionConcat,我们可以使用它来表明除非unionConcat [] = []成立,否则我们无法获得关联性。我们稍后会记住这一点。

现在我们将执行归纳步骤,假设我们有一些xs :: [a] xs >>= return == xs,我们可以显示(x:xs) >>= return == x:xs吗?

(x:xs) >>= return
unionConcat (map return (x:xs))
unionConcat (return x : map return xs)
...
x : unionConcat (map return xs)
x : (xs >>= return)
x:xs                                   -- working upward from the bottom here

提供unionConcat ---

的另一个属性
unionConcat (return x : xs) = x : unionConcat xs

所以,即使在我们有unionConcat的定义之前,我们已经可以说我们的属性将依赖于它自身的某些属性。我们应该将(:)构造函数转换回集合的概念。

unionConcat (return x : xs) = insert x (unionConcat xs)

答案 2 :(得分:0)

> U :: [Setx] --> Set x 
> 
> (m >>= f) >>= g ≡  m >>= (\x -> f x >>= g)
> VL(leftSide)
> (m >>= f) >>= g
> (Set x >>= f) >>=g  <=>
> (U(map f x)) >>=g  <=> (U(map f x)=Set y)
> Set y >>= g           <=>
> 
> 
> HL:(right Side)
> m >>= (\x -> f x >>= g)        <=>
> Set x >>=(\x -> f x >>= g) (funktionen \x -> f x gives a Set y it will consume value of  x.)

但这个prrof我错了。 (U = UnionMult。) 我被告知我应该尝试为左侧和右侧创建一个功能配置。它将有助于显示右侧和左侧相等。 HL:右边 VL左侧 想显示VL == HL