Some lambda calculus examples
Syntax
In a previous blog entry I described a simple evaluator and type checker for the lambda cube, i.e., various forms of lambda calculus.Here I'm going to show some examples of code in pure typed λ-calculus. All the examples are typable in Fω; the full lambda cube is not necessary.
Before doing any examples we'd better have some syntax that is not too painful, because writing λ-expression in raw Haskell is tedious. The syntax for variables, * kind, and application is easy, I'll just use Haskell syntax. For λ-expressions the Haskell syntax doesn't allow explicit type annotations, but various Haskell compiler implement that extension, so I'll just pick that. So a λ will be written, "\ (var::type) -> expr". And as in Haskell I'll allow multiple variables between the "\" and "->"; it's just a shorthand for multiple lambdas.
So what about the dependent function type? The syntax (x:t)→u suggests (x::t)->u, so I'll use that. And when the variable doesn't occur we'll write t->u as usual. For type variables Haskell (well, not Haskell 98, but extensions) uses forall (a::*) . t, so I'll allow that too.
An example, the identity function:
\ (a::*) (x::a) -> xwith type
forall (a::*) . a->aAnd using it
id Int 5Writing a pretty printer and parser for this is pretty straight forward so I'll skip that and just point you to the code. BTW, instead of using Parsec for the parser like everyone else I used ReadP. The ReadP library is very nice, partly because the alternative operator is actually commutative (unlike Parsec). But the error messages suck.
Enter let
Now if we want to use, say, the identity function more than once we need to name it. There is a mechanism for that, namely λ. But it looks awkward. Look:(\ (id :: forall (a::*) . a->a) -> ... id ... id ... id ...) (\ (a::*) (x::a) -> x)What makes it awkward is that the name, id, is far away from the body, \ (a::*) (x::a) -> x. From Haskell we are more used the let and where expressions. So let's add that let. Instead of what we have above we'll write
let id :: forall (a::*) . a->a = \ (a::*) (x::a) -> x in ... id ... id ... id ...The let construct could be just be syntactic suger for a lambda and an application, but I've decided to add it as a constructor to the expression type instead.
| Let Sym Type Expr Expr
Adding a new constructor means that we have to modify all the functions operating on Expr, and it's extra much work because Let is a variable binding construct.
For substitution we just cheat a little and use the expansion into an application and λ
sub (Let i t e b) = let App (Lam i' t' b') e' = sub (App (Lam i t b) e)
in Let i' t' e' b'
And for normal form we use the same trick.
spine (Let i t e b) as = spine (App (Lam i t b) e) as
And for now, let's extend the type checker in the same way.
To make definitions a little less verbose I'll allow multiple bindings. E.g.
let x :: Int = g a; y :: Int = f x in h x yIt's just multiple nested Lets in the obvious way. Another shorthand. I'll allow the identity function to be written
let id (a::*) (x::a) :: a = x in ...The translation is pretty easy
let f (x1::t1) ... (xn::tn) :: t = b in eis
let f :: forall (x1::t1) ... (xn::tn) . t = \ (x1::t1) ... (xn::tn) -> b in eAnd finally, to make it even more like Haskell, I'll allow the type signature to be on a line of its own, omitting types on the bound variables.
let id :: forall (a::*) . a -> a;
id a x = x;
in ...
It's pretty easy to translate to the bare expression type. Why all these little syntactic extras? Well, remember Mary Poppins "A spoonful of sugar makes the medicine go down."
Phew! Enough syntax, on to the examples.
Bool
We could start by throwing in all kinds of primitive types into our little language, but who knows what might happen then. All the nice properties that have been shown about the language might not hold anymore. So instead we'll code all the types we need with what we already have.The Bool type has two values: False and True. So we need to find a type that has exactly two different values. Fortunately that's easy: a->a->a (I'll be a bit sloppy and leave off top level quantifier sometimes, just like Haskell; That should be forall (a::*) . a->a->a).
Why does that have two possible values? Well, we have a function type that must return an a for any possible a that it's given, so it can't conjure up the return value out of thin air. It has to return one of it's arguments. And there are two arguments to choose from, so there are two different values in that type. Here's Bool, False, True:
Bool :: *; Bool = forall (a::*) . a->a->a; False :: Bool; False = \ (a::*) (x::a) (y::a) -> x; True :: Bool; True = \ (a::*) (x::a) (y::a) -> y;If the definition for Bool was written in Haskell it would be
type Bool = forall a . a->a->a false :: Bool false = \ x y -> x true :: Bool true = \ x y -> yIt would be easy to add more sugar and allow type which just means you're defining something of type *. And you could also make an omitted type in a forall mean type *. But I've not added these little extras.
Defining the if function is trivial; it's just a matter of permuting the arguments a little, because the boolean values come with the "if" built in.
if :: forall (a::*) . Bool -> a -> a -> a; if a b t f = b a t f;Note how the type signature is exactly the same as you'd find in Haskell. A difference is that we have explicit type abstraction and type application. For instance, if takes a first argument that is the type of the branches. So when using if we must pass in a type.
Given this we can try to type check some simple code:
let Bool :: *;
Bool = forall (a::*) . a->a->a;
False :: Bool;
False = \ (a::*) (x::a) (y::a) -> x;
in False
Here is what happens:
*CubeExpr> typeCheck $ read "let Bool :: *; Bool = forall (a::*) . a->a->a; False :: Bool;False = \\ (a::*) (x::a) (y::a) -> x; in False"
*** Exception: Type error:
Bad function argument type:
Function: \ (False :: Bool) -> False
argument: \ (a :: *) (x :: a) (y :: a) -> x
expected type: Bool
got type: forall (a :: *) . a->a->a
What is it whining about? Expected Bool, got forall (a :: *) . a->a->a. But it says right there in the code that Bool is exactly that. What's going on?
Well, the type checker knows the type of everything, but not the value of anything. So the type checker knows that type of Bool is *, but it doesn't know what it is equal to.
The problem is that when we have a let binding we know the value of the defined variable and to be able to do dependent type checking the type checker needs to know it too. We need to change the type checking of let. Here's a simple solution:
tCheck r (Let s t a e) = do
tCheck r t
ta <- tCheck r a
when (not (betaEq ta t)) $ throwError $ "Bad let def\n" ++ show (ta, t)
te <- tCheck r (subst s a e)
tCheck r (Pi s t te)
return te
Note how we substitute the value of the definition (a) in the body before type checking it. This is a sledge hammer approach. A better one would be to change the environment in the type checker to carry values when they are known. These values could then be used when computing the normal form of an expression. But let's keep it simple for now.
Let's try again:
*CubeExpr> typeCheck' $ read "let Bool :: *; Bool = forall (a::*) . a->a->a; False :: Bool;False = \\ (a::*) (x::a) (y::a) -> x; in False" forall (a :: *) . a->a->aThat worked!
A simple top level
To make experimentation easier I've added a simple top level where you can evaluate expression, make definitions, load files, etc. The files are just a bunch of definitions the way they would go inside a let.Sample session:
Welcome to the Cube. Use :help to get help. Cube> \ (a::*) (x::a) -> x \ (a :: *) (x :: a) -> x :: forall (a :: *) . a->a Cube>When evaluating an expression it will first print the value, then ::, and finally the type.
Let's try some more. Here's the file bool.cube.
-- The Bool type. Bool :: *; Bool = forall (boolT::*) . boolT->boolT->boolT; False :: Bool; False = \ (boolT::*) (false::boolT) (true::boolT) -> false; True :: Bool; True = \ (boolT::*) (false::boolT) (true::boolT) -> true; if :: forall (a::*) . Bool -> a -> a -> a; if a b t f = b a f t; not :: Bool -> Bool; not b = if Bool b False True; and :: Bool -> Bool -> Bool; and x y = if Bool x y False; or :: Bool -> Bool -> Bool; or x y = if Bool x True y;Note how I've named some of the type variables with more suggestive names. More about that in a moment.
Cube> :load bool.cube Cube> True \ (boolT :: *) (false :: boolT) (true :: boolT) -> true :: forall (boolT :: *) . boolT->boolT->boolT Cube> and True False \ (boolT :: *) (false :: boolT) (true :: boolT) -> false :: forall (boolT :: *) . boolT->boolT->boolTBy staring carefully at these you can convince yourself that it's right. What's making it a little hard to read are all those leading lambdas (and the corresponding function types). But there's an option to suppress the printing of them.
Cube> :skip Cube> True true :: boolT Cube> and True False false :: boolTLook, it got deceptively readable.
Characters
So we can define booleans. What about something like characters? You can define those too. What is the ASCII type? It's a type with 128 different values. We saw how we can make a type with two values (Bool); we can do the same for 128. Since that takes a lot of room, I'll do it for just four values.
Char :: *;
Char = forall (charT::*) . charT->charT->charT->charT->charT;
'a' :: Char;
'a' = \ (charT::*) (_'a'::charT) (_'b'::charT) (_'c'::charT) (_'d'::charT) -> _'a';
'b' :: Char;
'b' = \ (charT::*) (_'a'::charT) (_'b'::charT) (_'c'::charT) (_'d'::charT) -> _'b';
'c' :: Char;
'c' = \ (charT::*) (_'a'::charT) (_'b'::charT) (_'c'::charT) (_'d'::charT) -> _'c';
'd' :: Char;
'd' = \ (charT::*) (_'a'::charT) (_'b'::charT) (_'c'::charT) (_'d'::charT) -> _'d';
eqChar :: Char -> Char -> Bool;
eqChar x y = x Bool (y Bool True False False False)
(y Bool False True False False)
(y Bool False False True False)
(y Bool False False False True);
Since single quotes are allowed in identifiers in my little language the 'a' is just an identifier as usual.
Some sample use:
Cube> :load char.cube Cube> 'a' _'a' :: charT Cube> eqChar 'a' 'a' true :: boolT Cube> eqChar 'a' 'b' false :: boolT
A different way to use characters is just to assume that there is some character type and that is has some values. How can we do that? By using a lambda expression.
\ (Char :: *) -> \ ('a' :: Char) ('b' :: Char) ... -> ...
One final little syntactic sugar is to allow lambda expressions to be written with let.
So
let x :: T; in eis the same as
\ (x :: T) -> eSo for Char we can write
Char :: *; 'a' :: Char; 'b' :: Char; 'c' :: Char; 'd' :: Char; eqChar :: Char -> Char -> Bool;This is a very handy notation during program development, btw. Inside i let you can first just write the type of something and then use it freely. This something will then be lambda abstracted until such a time that you provide the definition.
Let's try the "fake" characters.
Cube> :load extchar.cube
Cube> 'a'
'a'
::
Char
Cube> :skip
Cube> 'a'
\ (Char :: *) ('a' :: Char) ('b' :: Char) ('c' :: Char) ('d' :: Char)
(eqChar :: Char->Char->forall (boolT :: *) . boolT->boolT->boolT)
-> 'a'
::
forall (Char :: *) .
Char->Char->Char->Char->
(Char->Char->forall (boolT :: *) . boolT->boolT->boolT)->
Char
Cube> :skip
Cube> eqChar 'a' 'b'
eqChar 'a' 'b'
::
forall (boolT :: *) . boolT->boolT->boolT
Now eqChar no longer gets evaluated, naturally, because it has no definition; it's λ bound.
Now we know how the Char type could be implemented (or supplied from the outside). It would then be all right to add it as a primitive (with the same behavior), because it will not ruin any properties. (Speaking of ruining properties, the seq function in Haskell is an example of a function that cannot be defined in the λ-calculus. And sure enough, adding it to Haskell ruined the validity of η-reduction.)
It's not difficult to extend the Expr type with some Prim constructor for primitive functions, and adding some special cases in the syntax and type checking for them. But since this is not intended to be a usable language I'll resist the temptation (for now).
Pairs
OK, booleans and characters were pretty easy. Let's do pairs next. The Pair type is parameterized over two types; the type of the first and the second component. As with booleans the representation of pairs come with the case analysis "build in". (Case analysis on pairs is flip uncurry in Haskell.) If we can correctly implement building pairs, fst, and snd we are done.Pair :: * -> * -> *; Pair a b = forall (pairT::*) . (a->b->pairT) -> pairT; PairC :: forall (a::*) (b::*) . a -> b -> Pair a b; PairC a b x y = \ (pairT::*) (pair :: a->b->pairT) -> pair x y; fst :: forall (a::*) (b::*) . Pair a b -> a; fst a b p = p a (\ (x::a) (y::b) -> x); snd :: forall (a::*) (b::*) . Pair a b -> b; snd a b p = p b (\ (x::a) (y::b) -> y);So the type is called Pair and the constructor PairC. Since they live in the same name space we can't use Haskell's convention of giving them the same name (which is (,) in Haskell.).
Again, in Haskell the first definition would be
type Pair a b = forall pairT . (a->b->pairT) -> pairTStaring at these definitions makes it obvious(?) that they work. But we can test it too.
Cube> :let S :: *; s :: S; T :: *; t :: T Cube> :load pair.cube Cube> :let p :: Pair S T; p = PairC S T s t Cube> p pair s t :: pairT Cube> fst S T p s :: S Cube> snd S T p t :: TThe :let command is used to make bindings without having to load them from a file. The first :let just introduces some values to play with.
Again, the big difference compared to Haskell is that all types are explicit. (But users of templates in C++ or generics in Java/C# might appeciate it?)
Maybe
We can follow the same pattern and define Haskell's Maybe type. In fact any non-recursive Haskell data type has a mechanical translation and easy into lambda calculus. We've seen boolean, characters, and pairs above.Maybe :: * -> *; Maybe a = forall (maybeT::*) . maybeT->(a->maybeT)->maybeT; Nothing :: forall (a::*) . Maybe a; Nothing a = \ (maybeT::*) (nothing::maybeT) (just::a->maybeT) -> nothing; Just :: forall (a::*) . a -> Maybe a; Just a x = \ (maybeT::*) (nothing::maybeT) (just::a->maybeT) -> just x; maybe :: forall (a::*) (r::*) . r -> (a->r) -> Maybe a -> r; maybe a r nothing just s = s r nothing just;
Natural numbers
Let's carry on with some natural numbers. Natural numbers are trickier because it's a recursive type. In Haskell:data Nat = Zero | Succ NatLet's try the cube version:
Cube> :load nat.cube Cube> 2 succ (succ zero) :: natT Cube> add 2 3 succ (succ (succ (succ (succ zero)))) :: natTWhat does the definitions for natural numbers look like?
Nat :: *; Nat = forall (natT::*) . natT -> (natT->natT) -> natT; 0 :: Nat; 0 = \ (natT::*) (zero::natT) (succ::natT->natT) -> zero; Succ :: Nat -> Nat; Succ n = \ (natT::*) (zero::natT) (succ::natT->natT) -> succ (n natT zero succ); natprim :: forall (r::*) . (r->r) -> r -> Nat -> r; natprim r succ zero n = n r zero succ; add :: Nat -> Nat -> Nat; add x y = x Nat y Succ; mul :: Nat -> Nat -> Nat; mul x y = x Nat 0 (add y); power :: Nat -> Nat -> Nat; power x y = y Nat (Succ 0) (mul x); isZero :: Nat -> Bool; isZero n = n Bool True (\ a::Bool -> False); 1 :: Nat; 1 = Succ 0; 2 :: Nat; 2 = Succ 1; 3 :: Nat; 3 = Succ 2;The natprim function corresponds to foldr for list and is our means of recursion. This type for natural numbers come with primitive recursion built in, just as the non-recursive data types earlier came with case analysis built in.
I'll skip defining subtraction&co, they are possible, but a little tedious (and very inefficient).
Lists
Lists are like a hybrid of natural numbers and the Maybe type. They follow the same pattern as before.List :: * -> *; List e = forall (listT::*) . listT -> (e->listT->listT) -> listT; Nil :: forall (e::*) . List e; Nil e = \ (listT::*) (nil::listT) (cons::e->listT->listT) -> nil; Cons :: forall (e::*) . e -> List e -> List e; Cons e x xs = \ (listT::*) (nil::listT) (cons::e->listT->listT) -> cons x (xs listT nil cons);And some sample functions.
foldr :: forall (a::*) (b::*) . (a->b->b) -> b -> List a -> b; foldr a b f z xs = xs b z f; map :: forall (a::*) (b::*) . (a->b) -> List a -> List b; map a b f xs = foldr a (List b) (\ (x::a) (r::List b) -> Cons b (f x) r) (Nil b) xs; append :: forall (a::*) . List a -> List a -> List a; append a xs ys = foldr a (List a) (Cons a) ys xs; foldl :: forall (a::*) (b::*) . (b->a->b) -> b -> List a -> b; foldl a b f z xs = foldr a (b->b) (\ (x::a) (g::b->b) (v::b) -> g (f v x)) (\ (x::b) -> x) xs z; reverse :: forall (a::*) . List a -> List a; reverse a xs = foldl a (List a) (\ (r :: List a) (x :: a) -> Cons a x r) (Nil a) xs;And a test:
Welcome to the Cube. Use :help to get help. Cube> :load bool.cube Cube> :load nat.cube Cube> :load list.cube Cube> :load pair.cube Cube> :load listmisc.cube Cube> :load extchar.cube Cube> :skip Cube> replicate Char 3 'b' cons 'b' (cons 'b' (cons 'b' nil)) :: listT Cube> :quitAnd with that, I'll quit too for now.
Labels: Haskell, Lambda calculus

26 Comments:
Hello I just entered before I have to leave to the airport, it's been very nice to meet you, if you want here is the site I told you about where I type some stuff and make good money (I work from home): here it is
看房子,買房子,建商自售,自售,台北新成屋,台北豪宅,新成屋,豪宅,美髮儀器,美髮,儀器,髮型,EMBA,MBA,學位,EMBA,專業認證,認證課程,博士學位,DBA,PHD,在職進修,碩士學位,推廣教育,DBA,進修課程,碩士學位,網路廣告,關鍵字廣告,關鍵字,課程介紹,學分班,文憑,牛樟芝,段木,牛樟菇,日式料理, 台北居酒屋,日本料理,結婚,婚宴場地,推車飲茶,港式點心,尾牙春酒,台北住宿,國內訂房,台北HOTEL,台北婚宴,飯店優惠,台北結婚,婚宴場地,推車飲茶,港式點心,尾牙春酒,住宿,訂房,HOTEL,飯店,造型系列,學位,牛樟芝,腦磷脂,磷脂絲胺酸,SEO,婚宴,捷運,學區,美髮,儀器,髮型,牛樟芝,腦磷脂,磷脂絲胺酸,看房子,買房子,建商自售,自售,房子,捷運,學區,台北新成屋,台北豪宅,新成屋,豪宅,學位,碩士學位,進修,在職進修, 課程,教育,學位,證照,mba,文憑,學分班,網路廣告,關鍵字廣告,關鍵字,SEO,关键词,网络广告,关键词广告,SEO,关键词,网络广告,关键词广告,SEO,台北住宿,國內訂房,台北HOTEL,台北婚宴,飯店優惠,住宿,訂房,HOTEL,飯店,婚宴,台北住宿,國內訂房,台北HOTEL,台北婚宴,飯店優惠,住宿,訂房,HOTEL,飯店,婚宴,台北住宿,國內訂房,台北HOTEL,台北婚宴,飯店優惠,住宿,訂房,HOTEL,飯店,婚宴,結婚,婚宴場地,推車飲茶,港式點心,尾牙春酒,台北結婚,婚宴場地,推車飲茶,港式點心,尾牙春酒,結婚,婚宴場地,推車飲茶,港式點心,尾牙春酒,台北結婚,婚宴場地,推車飲茶,港式點心,尾牙春酒,結婚,婚宴場地,推車飲茶,港式點心,尾牙春酒,台北結婚,婚宴場地,推車飲茶,港式點心,尾牙春酒,居酒屋,燒烤,美髮,儀器,髮型,美髮,儀器,髮型,美髮,儀器,髮型,美髮,儀器,髮型,小套房,小套房,進修,在職進修,留學,證照,MBA,EMBA,留學,MBA,EMBA,留學,進修,在職進修,牛樟芝,段木,牛樟菇,關鍵字排名,網路行銷,关键词排名,网络营销,網路行銷,關鍵字排名,关键词排名,网络营销,PMP,在職專班,研究所在職專班,碩士在職專班,PMP,證照,在職專班,研究所在職專班,碩士在職專班,SEO,廣告,關鍵字,關鍵字排名,網路行銷,網頁設計,網站設計,網站排名,搜尋引擎,網路廣告,SEO,廣告,關鍵字,關鍵字排名,網路行銷,網頁設計,網站設計,網站排名,搜尋引擎,網路廣告,SEO,廣告,關鍵字,關鍵字排名,網路行銷,網頁設計,網站設計,網站排名,搜尋引擎,網路廣告,SEO,廣告,關鍵字,關鍵字排名,網路行銷,網頁設計,網站設計,網站排名,搜尋引擎,網路廣告,EMBA,MBA,PMP
,在職進修,專案管理,出國留學,EMBA,MBA,PMP
,在職進修,專案管理,出國留學,EMBA,MBA,PMP
,在職進修,專案管理,出國留學
住宿,民宿,飯宿,旅遊,住宿,民宿,飯宿,旅遊,住宿,民宿,飯宿,旅遊,住宿,民宿,飯宿,旅遊,住宿,民宿,飯宿,旅遊,住宿,民宿,飯宿,旅遊,住宿,民宿,飯宿,旅遊,美容,美髮,整形,造型,美容,美髮,整形,造型,美容,美髮,整形,造型,美容,美髮,整形,造型,美容,美髮,整形,造型,美容,美髮,整形,造型,美容,美髮,整形,造型,設計,室內設計,裝潢,房地產,設計,室內設計,裝潢,房地產,設計,室內設計,裝潢,房地產,設計,室內設計,裝潢,房地產,設計,室內設計,裝潢,房地產,設計,室內設計,裝潢,房地產,設計,室內設計,裝潢,房地產,設計,室內設計,裝潢,房地產,進修,在職進修,MBA,EMBA,進修,在職進修,MBA,EMBA,進修,在職進修,MBA,EMBA,進修,在職進修,MBA,EMBA,進修,在職進修,MBA,EMBA,進修,在職進修,MBA,EMBA,進修,在職進修,MBA,EMBA,住宿,民宿,飯店,旅遊,美容,美髮,整形,造型,設計,室內設計,裝潢,房地產,進修,在職進修,MBA,EMBA,羅志祥,周杰倫,五月天,蔡依林,林志玲,羅志祥,周杰倫,五月天,蔡依林,林志玲,羅志祥,周杰倫,五月天,蔡依林,羅志祥,周杰倫,五月天,蔡依林
How to get more Anarchy credits. He gave me some Anarchy Online credits, he said that I could buy AO credits, but I did not have money, then I played it all my spare time. From then on, I got some Anarchy gold, if I did not continue to play it, I can sell Anarchy online gold to anyone who want.
To every game player angels gold is very import. My friend gave me some angels online gold, he said that I could buy angels gold, but I did not have money, then I played it all my spare time. From then on, I got some cheap angels online gold.
Now do you worried about that in the game do not had enough aion kina to play the game, now you can not worried, my friend told me a website, in here you can buy a lot aion online kina and only spend a little money, do not hesitate, it was really, in here we had much aion gold, we can sure that you will get the cheap aion kina, quick to come here to buy aion kina.
Now do you worried about that in the game do not had enough Anarchy credits to play the game, now you can not worried, my friend told me a website, in here you can buy a lot Anarchy Online credits and only spend a little money, do not hesitate, it was really, in here we had much Anarchy gold, we can sure that you will get the Anarchy online gold, quick to come here to buy AO credits.
mens clothing men's sweate, cheap columbia jackets, lacoste sweater, ralph lauren polo shirts,ski clothing. Free Shipping, PayPal Payment. Enjoy your shopping experience on mensclothingstore.us
nike tnEnter the necessary language
translation, up to 200 bytes winter, moves frequently in Chinanike chaussures showing that the deep strategy of the Chinese market. Harvard Business School, tn chaussures according to the relevant survey data show that in recent years the Chinese market three brands, Adidas, Li Ning market share at 21 percent, respectively,
puma shoes
chaussures pumacheap polos
polo shirts
ralph lauren polo shirtssport shoes
ugg boots
mp4
trade chinalacoste polo shirts
chaussure puma femmewedding dressestennis racket
cheap handbags
HAIR STRAIGHTENERS
I like your blog. Thank you. They are really great . Ermunterung ++ .
Some new style Puma Speed is in fashion this year.
chaussure puma is Puma shoes in french . Many Franzose like seach “chaussure sport” by the internet when they need buy the Puma Shoes Or nike max shoes. The information age is really convenient .
By the way ,the nike max ltd is really good NIKE air shoes ,don’t forget buy the puma mens shoes and nike air max ltd by the internet when you need them . Do you know Nike Air Shoes is a best Air Shoes . another kinds of Nike shoes is better . For example , Nike Air Rift is good and Cheap Nike Shoes .the nike shox shoes is fitting to running.
Spring is coming, Do you think this season is not for Ugg Boots? maybe yes .but this season is best time that can buy the cheap ugg boots. Many sellers are selling discounted. Do not miss . Please view my fc2 blog and hair straighteners blog.
.thank you .
I like orange converse shoes ,I like to buy the cheap converse shoes by the internet shop . the puma shoes and the adidas shoes (or addidas shoes) are more on internet shop .i can buy the cheap nike shoes and cheap puma shoes online. It’s really convenient.
Many persons more like Puma basket shoes than nike air rift shoes . the Puma Cat shoes is a kind of Cheap Puma Shoes .
If you want to buy the Cheap Nike Air shoes ,you can buy them online. They are same as the Nike Air shoes authorized shop. Very high-caliber Air shoes and puma cat shoes . the cheap puma shoes as same as other.
Cheap Brand Jeans ShopMen Jeans - True Religion Jeans, Women JeansGUCCI Jeans, Levi's Jeans, D&G Jeans, RED MONKEY Jeans, Cheap JeansArmani Jeans, Diesel Jeans, Ed hardy Jeans, Evisu Jeans, Jack&Jones Jeans...
There are ed hardy shirts
,pretty ed hardy shirt for men,
ed hardy womens in the ed hardy online store
designed by ed hardy ,
many cheap ed hardy shirt ,glasses,caps,trouers ed hardy shirts on sale ,
You can go to edhardyshirts.com to have a look ,you may find one of ed hardy clothing fit for you
Top qualitymen's jacket,
These cheap jacket are on sale now,you can find
north face jackets inmage on our web
Do you wannaghd hair straighteners for you own , we have many
cheap ghd hair straightenersin style and great,you can choose one from these
hair straighteners
Authentic chaussure puma
chaussure sport
And chaussure nike shoes
Come here to have a look of our Wholesale Jeans
Many fashionMens Jeans ,eye-catching
Womens Jeans ,and special out standing
Blue Jeans ,you can spend less money on our
Discount Jeans but gain really fine jeans, absolutely a great bargain.
www.crazypurchase.com
China Wholesale
wholesale from china
buy products wholesale
China Wholesalers
http://weddingdressseason.com
http://www.crazypurchase.com
Ralph Lauren Polo is the most famous sports shirt.Burberry Polo Shirt is the most well-known in France jerseys. The north face jacket is a winter essential goods.Columbia jacket and spyder jacket let people have more choice of clothes. Different brands have different design styles, but all it attracts us.
cheap tennis racquet
tennis racquet discount
cheap tennis racket
discount Tennis Racket
Modern tennis racquet in the manufacturing sector have been in use for close to the aerospace industry and military-industrial material products. Over the past two decades, metal materials and chemical materials to upgrade the high level of tennis racket manufacturer has laid a solid foundation. In today's big brands have more than tennis: Head junior tennis racket,Wilson tennis racquet, Wilson tennis racket,Head tennis racket,Babolat tennis racket......
ed hardy clothing
ed hardy clothes
ed hardy shirts
ed hardy t-shirts
ed hardy sunglasses
ed hardy mens
ed hardy womens
Wholesale Handbags
Cheap Handbags
Womens Handbags
Cheap Purses
Designer Handbags
Thank you so much!!polo shirt men'ssweate,cheap polo shirts cheap columbia jackets, lacoste sweater, ralph lauren polo shirts,ski clothing. Free Shipping, PayPal Payment. Enjoy your shopping experience on mensclothingus.com.We have mens polo shirts.
Awesome!!!Best wishes for you !!wholesale polo shirts is the father of the summer should be prepared to most commonly used item, it has both style and shape of polo clothing, and vest with a random function, so that in the short-sleeved apply to both on many occasions, the pink and black color men's polo shirts brought into effect, lightweight cotton, linen texture to demonstrate masculine temperament and sense of fashion exhaustively. polo shirts for sale
Wonderful!!You can find the father who desire fashionable, intellectual cheap polos simultaneously, you can find a psychologist to study the most harmonious of families should be pink mens clothing, so do not want to take the mature route for the father, buy cheap polos, the learn from such a walk in between the formal and casual styling, refined style to create a sense of mild authority.
Perfect!!You are a outstanding person!Have you ever wore chaussures puma, puma CAT,Puma shoes store gives some preview of puma speed cat,puma basket, puma speed, puma speed and other puma shoes. These puma sport items are at store recently and available for anyone.
Do not mean bad.Thank you so much!Men's polo shirts was the shirt of choice for diverse groups of teenagers.Brightly coloured polo shirts can make you look like a Day-glo dirigible.
Wonderful!You can find the father who desire fashionable eg,uggs fashion,you can enjoy uggs online here, intellectual polo shirt simultaneously.
fantastic!God bless you!Meanwhile,you can visit my China Wholesale,we have the highest quality but the lowest price fashion products wholesale from China.Here are the most popular China Wholesale products for all of you.Also the polo clothing is a great choice for you.
God bless you!I really agree with your opinions.Also,there are some new fashion things here,gillette razor blades.gillette mach3 razor bladesfor men.As for ladies,gillette venus razor blades must the best gift for you in summer,gillette fusion blades are all the best choice for you.
cheap hair straighteners
chi hair straightener
chi flat iron
new polo shirts
cheap Lacoste polo shirts
cheap Lacoste polo shirts
cheap handbags
cheap bags
puma chaussures
chaussures puma
chaussure puma
Men's North Face
Women's North Face
hair straighteners
sexy lingerie store
cheap ugg boots
tattoo wholesale
men's clothing
women's clothing
2009 nike shoes
new nike shoes
Women's max
Men's max 93
nike shox
Nike air force
Nike air max 2003
nike air max ltd
nike air max tn
Nike air rift
Nike air Yeezy
nike airmax
Nike air max 90
Nike air max 97
nike birds nest shoes
nike dunk
nike RT1 shoes
nike SB
nike shox shoes
Nike shox OZ shoes
Nike shox R2 shoes
Nike shox R3 shoes
Nike shox R4 shoes
Nike shox R5 shoes
Nike shox TL3
nike trainers lovers
tennis rackets
Wilson tennis rackets
HEAD tennis rackets
Babolat tennis rackets
http://iblog99.edublogs.org/
http://iblog99.blog126.fc2.com/
http://iblog99.blogsome.com/
http://www.soulcast.com/iblog99/
視訊|影音視訊聊天室|視訊聊天室|視訊交友|視訊聊天|視訊美女|視訊辣妹|免費視訊聊天室
自慰器|自慰器
網頁設計|網頁設計公司|最新消息|訪客留言|網站導覽
免費視訊聊天|辣妹視訊|視訊交友網|美女視訊|視訊交友|視訊交友90739|成人聊天室|視訊聊天室|視訊聊天|視訊聊天室|情色視訊|情人視訊網|視訊美女
一葉情貼圖片區|免費視訊聊天室|免費視訊|ut聊天室|聊天室|豆豆聊天室|尋夢園聊天室|聊天室尋夢園|影音視訊聊天室||
Well, nice article buddy… Someone will love to read this infor if I tell her about this. She’s really interested in this subject. Thanks again… Please come visit my site Topeka Kansas Business Directory when you got time.
Wow, loving the two photos you posted. You got potential. Please come visit my site Thousand Oaks California Yellow Pages when you got time.
Post a Comment
<< Home