forall的意思就是数学中的"任取" ∀ ,没有更多含义级的东西了.看看haskell中的落实:
参考:
对于一般的泛型,forall都是隐含存在的.
启动forall的识别:
ghci >:set -XExistentialQuantification
.hs {-# LANGUAGE ExistentialQuantification #-}
forall在函数定义时是隐含的:
map :: (a -> b) -> [a] -> [b]
map :: forall a b. (a -> b) -> [a] -> [b]
一个意思
但是在构造data定义的时候:
data SB = SB x
data定义需要具体类型,这时如果想让SB成为泛型(polymorphic), 就需要forall了,
> data SB = forall x. (show x) => SB x
> instance Show SB where
> show (SB x) = show x
> x :: [SB]
> x = [SB 1, SB "xx", SB ()]
这样, SB就是拥有Show属性的泛型了.
x可以show,虽然SB并不知道其中元素的具体类型,但是他们都是Show的实例,都可以被show函数处理.
Bool 是 集合{True,False,⊥}
Stirng 是集合{⊥,"a","b","ab",....}
这些类的交集只有{⊥}
[forall a. a] 表示列表里的每个元素都是(forall a. a)类型的, 包含的对象都是⊥
[forall a. Show a => a] 包含的对象拥有交集Show
forall a. [a] 表示列表元素可以是任意的东西,
调用者可以把[a]看成任何的具体列表,注意这不是混合列表.
data T = forall a. MkT a -- 只要有a,就有MkT a.
等价于:
MkT :: forall a. a -> T
heteroList = [MkT 5, MkT (), MkT True, MkT map]
data T' = forall a. Show a => MkT' a
ST monad是非常复杂的用于IO的monad
对应的函数:
runST :: forall a. (forall s. ST s a) -> a
(runST :: ST s a -> a)
两层的forall对应专业术语"rank-2 polymorphism"
ST可以被修改状态.
STRef表示对一个状态的引用,是ST内部的映射关系.
newSTRef :: a -> ST s (STRef s a)
readSTRef :: STRef s a -> ST s a
writeSTRef :: STRef s a -> a -> ST s ()
对ST的操作就是从一些引用到一些值的操作, ST初始的时候就是空的引用和空的值.
如果使用不良的代码操作ST:
let v = runST (newSTRef True)
in runST (readSTRef v)
编译器在类型检查的时候:
newSTRef True :: forall s. ST s (STRef s Bool)
runST :: forall a. (forall s. ST s a) -> a
把两个第一个带入第二个:
** together, forall a. (forall s. ST s (STRef s Bool)) -> STRef s Bool
里面的forall s.作用范围在括号内部,后面带入的(STRef s Bool),
类型检测是就会说不匹配,因为它不被forall所涉及.
** together, forall a. (forall s'. ST s' (STRef s' Bool)) -> STRef s Bool
注意, 里面很灵活,但是一旦返回了就会又受到限制.
--
定义灵活的数据类型:
newtype Pair a b=Pair (forall c. (a->b->c)->c)
可以定义函数类型返回任意的值,此时函数可以还没有出现!相当于接口/抽象.
阅读(1178) | 评论(0) | 转发(0) |