Haskell風range表記

Haskellのリスト表記便利だわーと思ったのでpythonでそれっぽく。使用に堪えるかどうかはしらん。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import operator
import re

#
# Haskell-like range notation
#
def hrange(pattern):
    _numeric_pattern = r'-?\d+(\.\d+)?'
    _range_pattern = re.compile(r'\[(?P<first>{0})\s*(,\s*(?P<second>{0}))?\s*\.\.\s*(?P<end>{0})?\]'.format(_numeric_pattern))

    # generator factory
    def countgen(first, second, end):
        def gen():
            now = first
            step = second - first
            ope = operator.le if step>0 else operator.ge
            while (end is None) or ((end is not None) and ope(now, end)):
                yield now
                now += step
        return gen()

    # string to (int|float)
    def toVal(numstr):
        try:
            if numstr is None:
                return None
            elif re.match(r'^-?\d+$', numstr):
                return int(numstr)
            else:
                return float(numstr)
        except ValueError:
            return None

    m = _range_pattern.match(pattern)
    if m:
        first, second, end = [toVal(m.group(x)) for x in ('first', 'second', 'end')]
        if not second:
            second = first+1
        
        return countgen(first, second, end)
    else:
        raise ValueError()

'''\
usage: 
[first_value(,second_value)..(end_value)]

hrange('[1,2..10]') => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
hrange('[1,3..10]') => [1, 3, 5, 7, 9]
hrange('[1,2.5..10]') => [1, 2.5, 4.0, 5.5, 7.0, 8.5, 10.0]
hrange('[4,3..0]') => [4, 3, 2, 1, 0]
hrange('[0,5..]') => [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, ... 
hrange('[1,1..]') => [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
hrange('[10..]') => [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, ...
'''