Convert to ASCII Agrippa Numbers Challenge

Given a natural number, output it in the ASCII form of Agrippa's number system.

Description

I like odd alphabets and numeral systems. My favorite numeral system is one given by Heinrich Cornelius Agrippa. It gives a succinct way to write numbers in the range [0,9999], where single digits are written as follows:



Larger numbers less than 10^4 are a combination of single digits, but rotated/horizontally-mirrored on a single central bar as follows: 

[0° mirrored, 10's  ] | [0°,            1's  ]
[180°,        1000's] | [180° mirrored, 100's]


Here are a few examples:



The ASCII equivalents are:

Ones:
  0  1  2  3  4  5  6  7  8  9
  |  |- |_ |\ |/ |~ || |^ |v |]
  |  |  |  |  |  |  |  |  |  |

Tens:
  0  1  2  3  4  5  6  7  8  9
  | -| _| /| \| ~| || ^| v| [|
  |  |  |  |  |  |  |  |  |  |

Hundreds:
  0  1  2  3  4  5  6  7  8  9
  |  |  |  |  |  |  |  |  |  |
  |  |_ |- |/ |\ |~ || |v |^ |]

Thousands:
  0  1  2  3  4  5  6  7  8  9
  |  |  |  |  |  |  |  |  |  |
  | _| -| \| /| ~| || v| ^| [|

 1510:  1511:  1471:  1486:  3421:
 -|     -|-    ^|-    v||    _|-
 _|~    _|~    _|\    -|\    \|\


Numbers larger than 9999 are broken up into sections of 4 digits (with leading zeros added to get a multiple of four) and each is converted. For example:

314159: (0031 4159)
         /|-  ~|]
          |   /|_


Rules


Your answer may be a function or full program
The input is a positive integer 
Entries must support inputs over 10^8
Each four digit section takes exactly six characters
Sections of four are separated by a single space
Trailing newline is optional 
Up to two trailing spaces per line are allowed
I will not accept my own answer
Score is in bytes, lowest score wins!
Haskell, 310 bytes


Defining reverse (as I did: r) is one byte shorter than importing Data.List and using it just once
Defining z=0:z and (!)=(!!).(++z) is the shortest way yet that I've found to return 0 for out of bounds
I've checked and quickChecked the take4s function, but it still feels like magic to me


Here's the code:

l=lines"    \n--__\n__--\n\\//\\\n/\\\\/\n~~~~\n||||\n^^vv\nvv^^\n][]["
d x|x&lt;1=[]|1&lt;2=mod x 10:d(div x 10)
(&amp;)=(!!)
z=(0::Int):z
(!)=(&amp;).(++z)
t a=[[a!q|q&lt;-[p..p+3]]|p&lt;-[0,4..length a-1]]
g[c,d,b,a]=[[l&amp;b&amp;1,'|',l&amp;a&amp;0,' '],[l&amp;d&amp;3,'|',l&amp;c&amp;2,' ']]
r[]=[]
r(x:y)=r y++[x]
f=unlines.foldl1(zipWith(++)).map g.r.t.d


Less golfed:

import Data.List (reverse)

dict = lines "    \n--__\n__--\n\\//\\\n/\\\\/\n~~~~\n||||\n^^vv\nvv^^\n][]["


-- Note that (digits x) returns the digits of x in little-endian order
digits x  | x &lt; 1     = []
          | otherwise = mod x 10 : digits (div x 10)

-- Note: zeros needs the type signature, because otherwise it won't match [Int] (inferred from (!!))
zeros = (0::Int) : zeros

-- list ! position gives the element at the position, or 0 for out of bounds
(!) = (!!) . (++zeros)

-- This partitions the digits into groups of four, padded right
take4s a = [[a!q | q &lt;-[p..p+3]] | p &lt;- [0,4..length a - 1]]

convertOne[c,d,b,a] = [[dict !! b !! 1, '|', dict !! a !! 0, ' '], [dict !! d !! 3, '|', dict !! c !! 2, ' ']]

f = unlines . foldl1(zipWith (++)) . map convertOne . reverse . take4s . digits


Tests (escape characters removed):

mapM_ print $ lines $ f 1510
-|  
_|~ 

mapM_ print $ lines $ f 1511
-|- 
_|~ 

mapM_ print $ lines $ f 1471
^|- 
_|\ 

mapM_ print $ lines $ f 1486
v|| 
_|\ 

mapM_ print $ lines $ f 3421
_|- 
\|\ 

mapM_ print $ lines $ f 1234567891011121314
_|\ ||^ -|  -|_ -|/ 
 |_ /|~ ^|] _|_ _|/ 

mapM_ print $ lines $ f 1024628340621757567
 |_ _|v  || ^|~ ||^ 
 |_ /|| \|\ -|_ v|~