объединение двух ленивых списков, конфликт типов

Почему моя функция merge жалуется на свой тип?

Разве мой x не type 'a seq?

type 'a seq = Stop | Cons of 'a * (unit -> 'a seq)

let rec linear start step= (*builds a seq starting with 'start'*)
    Cons (start, fun () -> linear (start+step) step)

let rec take n seq = match seq with (*take first n elem from seq*)
| Stop -> []
| Cons (a, f) -> if n < 1 then [] else a::(take (n-1) (f ()))

let rec merge seq1 seq2 = match seq1, seq2 with 
    | Stop, _ -> seq2
    | _, Stop -> seq1
    | Cons(h1, tf1), _ as x -> 
        Cons(h1, fun () -> merge (x) (tf1 ()))

let l1 = linear 1 1
let l2 = linear 100 100 
let l3 = interleave l1 l2

Я хотел бы увидеть правильный результат для

take 10 l3

целый список = [1; 100; 2; 200; 3; 300; 4; 400; 5; 500]

Другой способ написать мою функцию (которая работает) будет

let rec merge seq1 seq2 = match seq1 with
| Stop -> Stop
| Cons (h, tf) -> Cons(h, fun () -> merge seq2 (tf ()))

но я не понимаю, почему первый merge не работает.

Спасибо.


person Oleg    schedule 09.03.2017    source источник


Ответы (1)


Просто напишите (_ as x), потому что здесь ваш as x улавливает весь шаблон.

Итак, что вы видите:

| Cons(h1, tf1), (_ as x) -> ...

на самом деле анализируется как

| (Cons(h1, tf1), _) as x -> ...

И вы действительно могли бы написать:

| Cons(h1, tf1), x -> ...

Что намного лучше ;-)

Или даже

| Cons(h1, tf1), _ -> Cons(h1, fun () -> merge seq2 (tf1 ()))
person Lhooq    schedule 09.03.2017