#include <iostream>
#include <type_traits>

template <int I> using int_ = std::integral_constant<int, I>;

template<typename T> using eval = typename T::type;

template<typename... List>
struct seq
{
    using type = seq;
};

template<typename> struct car;
template<typename Car, typename... Cdr>
struct car< seq<Car, Cdr...>>
{
    typedef Car type;
};

template<typename> struct cdr;
template<typename Car, typename... Cdr>
struct cdr< seq<Car, Cdr...>>
{
    typedef seq<Cdr...> type;
};


template <typename, typename> struct cons;
template <typename T, typename... L>
struct cons<T, seq<L...>>
{
    typedef seq<T, L...> type;
};

template<typename, typename> struct concat;
template <typename... As, typename... Bs>
struct concat<seq<As...>, seq<Bs...>>
{
    typedef seq<As..., Bs...> type;
};

template<typename> struct length;
template<typename... As>
struct length<seq<As...>>
{
    typedef std::integral_constant<unsigned, sizeof...(As)> type;
};

template<typename>
struct is_empty
{
    typedef std::integral_constant<bool, true> type;
};

template<>
struct is_empty<seq<>>
{
    typedef std::integral_constant<bool, true> type;
};

template<template<typename... Args> class Fun, typename... Args>
struct apply
{
    typedef eval<Fun<Args...>> type;
};

typedef seq<int_<1>, int_<2>, int_<3> > s1;
typedef seq<int_<7>, int_<5>, int_<9> > s2;
typedef seq<int_<1>, s2, int_<17>, s1 > s3;
typedef seq<> empty;
template<typename Seq> using concat_fix = apply<concat, s2, Seq>;

int main()
{

    std::cerr << eval < length < eval < apply < concat, s1, s3 >> >> ::value << '\n';
    std::cerr << eval < length <eval< concat_fix<s3>>>>::value << '\n';
    std::cerr << eval < apply < length, empty> >::value << '\n';
    std::cerr << eval<length < eval < concat<s1, s3 >>>>::value << '\n';
    return 0;
}