{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE UndecidableInstances #-}
module Language.Hasmtlib.Type.Relation
(
Relation(..)
, relation, symmetric_relation, build, buildFrom, buildFromM, identity
, (!?), (!)
, bounds, indices, elems, assocs
, domain, codomain, image, preimage
, table
)
where
import Prelude hiding (and, (&&), any)
import Language.Hasmtlib.Type.MonadSMT
import Language.Hasmtlib.Type.SMTSort
import Language.Hasmtlib.Type.Expr
import Language.Hasmtlib.Boolean
import Language.Hasmtlib.Codec
import Data.Coerce
import Data.Array (Array, Ix(..))
import Data.Maybe
import qualified Data.Array as A
import Control.Monad
import Control.Lens hiding (indices)
newtype Relation a b = Relation (Array (a, b) (Expr BoolSort))
instance (Ix a, Ix b) => Codec (Relation a b) where
type Decoded (Relation a b) = Array (a, b) Bool
decode :: Solution -> Relation a b -> Maybe (Decoded (Relation a b))
decode Solution
s (Relation Array (a, b) (Expr 'BoolSort)
x) = Solution
-> Array (a, b) (Expr 'BoolSort)
-> Maybe (Decoded (Array (a, b) (Expr 'BoolSort)))
forall a. Codec a => Solution -> a -> Maybe (Decoded a)
decode Solution
s Array (a, b) (Expr 'BoolSort)
x
encode :: Decoded (Relation a b) -> Relation a b
encode Decoded (Relation a b)
x = Array (a, b) (Expr 'BoolSort) -> Relation a b
forall a b. Array (a, b) (Expr 'BoolSort) -> Relation a b
Relation (Array (a, b) (Expr 'BoolSort) -> Relation a b)
-> Array (a, b) (Expr 'BoolSort) -> Relation a b
forall a b. (a -> b) -> a -> b
$ Decoded (Array (a, b) (Expr 'BoolSort))
-> Array (a, b) (Expr 'BoolSort)
forall a. Codec a => Decoded a -> a
encode Decoded (Array (a, b) (Expr 'BoolSort))
Decoded (Relation a b)
x
instance (Ix a, Ix b, a ~ c, b ~ d) => Each (Relation a b) (Relation c d) (Expr BoolSort) (Expr BoolSort) where
each :: Traversal
(Relation a b) (Relation c d) (Expr 'BoolSort) (Expr 'BoolSort)
each Expr 'BoolSort -> f (Expr 'BoolSort)
f (Relation Array (a, b) (Expr 'BoolSort)
arr) = Array (c, d) (Expr 'BoolSort) -> Relation c d
forall a b. Coercible a b => a -> b
coerce (Array (c, d) (Expr 'BoolSort) -> Relation c d)
-> f (Array (c, d) (Expr 'BoolSort)) -> f (Relation c d)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Expr 'BoolSort -> f (Expr 'BoolSort))
-> Array (a, b) (Expr 'BoolSort)
-> f (Array (c, d) (Expr 'BoolSort))
forall s t a b. Each s t a b => Traversal s t a b
Traversal
(Array (a, b) (Expr 'BoolSort))
(Array (c, d) (Expr 'BoolSort))
(Expr 'BoolSort)
(Expr 'BoolSort)
each Expr 'BoolSort -> f (Expr 'BoolSort)
f Array (a, b) (Expr 'BoolSort)
arr
{-# INLINE each #-}
type instance Index (Relation a b) = (a,b)
type instance IxValue (Relation a b) = Expr BoolSort
instance (Ix a, Ix b) => Ixed (Relation a b) where
ix :: Index (Relation a b)
-> Traversal' (Relation a b) (IxValue (Relation a b))
ix Index (Relation a b)
i IxValue (Relation a b) -> f (IxValue (Relation a b))
f (Relation Array (a, b) (Expr 'BoolSort)
arr) = Array (a, b) (Expr 'BoolSort) -> Relation a b
forall a b. Coercible a b => a -> b
coerce (Array (a, b) (Expr 'BoolSort) -> Relation a b)
-> f (Array (a, b) (Expr 'BoolSort)) -> f (Relation a b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Index (Array (a, b) (Expr 'BoolSort))
-> Traversal'
(Array (a, b) (Expr 'BoolSort))
(IxValue (Array (a, b) (Expr 'BoolSort)))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Index (Array (a, b) (Expr 'BoolSort))
Index (Relation a b)
i IxValue (Array (a, b) (Expr 'BoolSort))
-> f (IxValue (Array (a, b) (Expr 'BoolSort)))
IxValue (Relation a b) -> f (IxValue (Relation a b))
f Array (a, b) (Expr 'BoolSort)
arr
{-# INLINE ix #-}
relation :: (Ix a, Ix b, MonadSMT s m) =>
((a,b),(a,b))
-> m (Relation a b)
relation :: forall a b s (m :: * -> *).
(Ix a, Ix b, MonadSMT s m) =>
((a, b), (a, b)) -> m (Relation a b)
relation ((a, b), (a, b))
bnd = do
[((a, b), Expr 'BoolSort)]
pairs <- [m ((a, b), Expr 'BoolSort)] -> m [((a, b), Expr 'BoolSort)]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
forall (m :: * -> *) a. Monad m => [m a] -> m [a]
sequence ([m ((a, b), Expr 'BoolSort)] -> m [((a, b), Expr 'BoolSort)])
-> [m ((a, b), Expr 'BoolSort)] -> m [((a, b), Expr 'BoolSort)]
forall a b. (a -> b) -> a -> b
$ do
(a, b)
p <- ((a, b), (a, b)) -> [(a, b)]
forall a. Ix a => (a, a) -> [a]
A.range ((a, b), (a, b))
bnd
m ((a, b), Expr 'BoolSort) -> [m ((a, b), Expr 'BoolSort)]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return (m ((a, b), Expr 'BoolSort) -> [m ((a, b), Expr 'BoolSort)])
-> m ((a, b), Expr 'BoolSort) -> [m ((a, b), Expr 'BoolSort)]
forall a b. (a -> b) -> a -> b
$ do
Expr 'BoolSort
x <- m (Expr 'BoolSort)
forall (t :: SMTSort) s (m :: * -> *).
(KnownSMTSort t, MonadSMT s m) =>
m (Expr t)
var
((a, b), Expr 'BoolSort) -> m ((a, b), Expr 'BoolSort)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ((a, b)
p, Expr 'BoolSort
x)
Relation a b -> m (Relation a b)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Relation a b -> m (Relation a b))
-> Relation a b -> m (Relation a b)
forall a b. (a -> b) -> a -> b
$ ((a, b), (a, b)) -> [((a, b), Expr 'BoolSort)] -> Relation a b
forall a b.
(Ix a, Ix b) =>
((a, b), (a, b)) -> [((a, b), Expr 'BoolSort)] -> Relation a b
build ((a, b), (a, b))
bnd [((a, b), Expr 'BoolSort)]
pairs
symmetric_relation ::
(MonadSMT s m, Ix b) =>
((b, b), (b, b))
-> m (Relation b b)
symmetric_relation :: forall s (m :: * -> *) b.
(MonadSMT s m, Ix b) =>
((b, b), (b, b)) -> m (Relation b b)
symmetric_relation ((b, b), (b, b))
bnd = do
[[((b, b), Expr 'BoolSort)]]
pairs <- [m [((b, b), Expr 'BoolSort)]] -> m [[((b, b), Expr 'BoolSort)]]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
forall (m :: * -> *) a. Monad m => [m a] -> m [a]
sequence ([m [((b, b), Expr 'BoolSort)]] -> m [[((b, b), Expr 'BoolSort)]])
-> [m [((b, b), Expr 'BoolSort)]] -> m [[((b, b), Expr 'BoolSort)]]
forall a b. (a -> b) -> a -> b
$ do
(b
p,b
q) <- ((b, b), (b, b)) -> [(b, b)]
forall a. Ix a => (a, a) -> [a]
A.range ((b, b), (b, b))
bnd
Bool -> [()]
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> [()]) -> Bool -> [()]
forall a b. (a -> b) -> a -> b
$ b
p b -> b -> Bool
forall a. Ord a => a -> a -> Bool
<= b
q
m [((b, b), Expr 'BoolSort)] -> [m [((b, b), Expr 'BoolSort)]]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return (m [((b, b), Expr 'BoolSort)] -> [m [((b, b), Expr 'BoolSort)]])
-> m [((b, b), Expr 'BoolSort)] -> [m [((b, b), Expr 'BoolSort)]]
forall a b. (a -> b) -> a -> b
$ do
Expr 'BoolSort
x <- m (Expr 'BoolSort)
forall (t :: SMTSort) s (m :: * -> *).
(KnownSMTSort t, MonadSMT s m) =>
m (Expr t)
var
[((b, b), Expr 'BoolSort)] -> m [((b, b), Expr 'BoolSort)]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([((b, b), Expr 'BoolSort)] -> m [((b, b), Expr 'BoolSort)])
-> [((b, b), Expr 'BoolSort)] -> m [((b, b), Expr 'BoolSort)]
forall a b. (a -> b) -> a -> b
$ ((b
p,b
q), Expr 'BoolSort
x)
((b, b), Expr 'BoolSort)
-> [((b, b), Expr 'BoolSort)] -> [((b, b), Expr 'BoolSort)]
forall a. a -> [a] -> [a]
: [ ((b
q,b
p), Expr 'BoolSort
x) | b
p b -> b -> Bool
forall a. Eq a => a -> a -> Bool
/= b
q ]
Relation b b -> m (Relation b b)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Relation b b -> m (Relation b b))
-> Relation b b -> m (Relation b b)
forall a b. (a -> b) -> a -> b
$ ((b, b), (b, b)) -> [((b, b), Expr 'BoolSort)] -> Relation b b
forall a b.
(Ix a, Ix b) =>
((a, b), (a, b)) -> [((a, b), Expr 'BoolSort)] -> Relation a b
build ((b, b), (b, b))
bnd ([((b, b), Expr 'BoolSort)] -> Relation b b)
-> [((b, b), Expr 'BoolSort)] -> Relation b b
forall a b. (a -> b) -> a -> b
$ [[((b, b), Expr 'BoolSort)]] -> [((b, b), Expr 'BoolSort)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[((b, b), Expr 'BoolSort)]]
pairs
build :: (Ix a, Ix b)
=> ((a,b),(a,b))
-> [((a,b), Expr BoolSort)]
-> Relation a b
build :: forall a b.
(Ix a, Ix b) =>
((a, b), (a, b)) -> [((a, b), Expr 'BoolSort)] -> Relation a b
build ((a, b), (a, b))
bnd [((a, b), Expr 'BoolSort)]
pairs = Array (a, b) (Expr 'BoolSort) -> Relation a b
forall a b. Array (a, b) (Expr 'BoolSort) -> Relation a b
Relation (Array (a, b) (Expr 'BoolSort) -> Relation a b)
-> Array (a, b) (Expr 'BoolSort) -> Relation a b
forall a b. (a -> b) -> a -> b
$ ((a, b), (a, b))
-> [((a, b), Expr 'BoolSort)] -> Array (a, b) (Expr 'BoolSort)
forall i e. Ix i => (i, i) -> [(i, e)] -> Array i e
A.array ((a, b), (a, b))
bnd [((a, b), Expr 'BoolSort)]
pairs
buildFrom :: (Ix a, Ix b)
=> ((a,b),(a,b))
-> ((a,b) -> Expr BoolSort)
-> Relation a b
buildFrom :: forall a b.
(Ix a, Ix b) =>
((a, b), (a, b)) -> ((a, b) -> Expr 'BoolSort) -> Relation a b
buildFrom ((a, b), (a, b))
bnd (a, b) -> Expr 'BoolSort
p = ((a, b), (a, b)) -> [((a, b), Expr 'BoolSort)] -> Relation a b
forall a b.
(Ix a, Ix b) =>
((a, b), (a, b)) -> [((a, b), Expr 'BoolSort)] -> Relation a b
build ((a, b), (a, b))
bnd ([((a, b), Expr 'BoolSort)] -> Relation a b)
-> [((a, b), Expr 'BoolSort)] -> Relation a b
forall a b. (a -> b) -> a -> b
$ (((a, b) -> ((a, b), Expr 'BoolSort))
-> [(a, b)] -> [((a, b), Expr 'BoolSort)])
-> [(a, b)]
-> ((a, b) -> ((a, b), Expr 'BoolSort))
-> [((a, b), Expr 'BoolSort)]
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((a, b) -> ((a, b), Expr 'BoolSort))
-> [(a, b)] -> [((a, b), Expr 'BoolSort)]
forall a b. (a -> b) -> [a] -> [b]
map (((a, b), (a, b)) -> [(a, b)]
forall a. Ix a => (a, a) -> [a]
A.range ((a, b), (a, b))
bnd) (((a, b) -> ((a, b), Expr 'BoolSort))
-> [((a, b), Expr 'BoolSort)])
-> ((a, b) -> ((a, b), Expr 'BoolSort))
-> [((a, b), Expr 'BoolSort)]
forall a b. (a -> b) -> a -> b
$ \ (a, b)
i -> ((a, b)
i, (a, b) -> Expr 'BoolSort
p (a, b)
i)
buildFromM :: (Ix a, Ix b, MonadSMT s m)
=> ((a,b),(a,b))
-> ((a,b) -> m (Expr BoolSort))
-> m (Relation a b)
buildFromM :: forall a b s (m :: * -> *).
(Ix a, Ix b, MonadSMT s m) =>
((a, b), (a, b))
-> ((a, b) -> m (Expr 'BoolSort)) -> m (Relation a b)
buildFromM ((a, b), (a, b))
bnd (a, b) -> m (Expr 'BoolSort)
p = do
[((a, b), Expr 'BoolSort)]
pairs <- [m ((a, b), Expr 'BoolSort)] -> m [((a, b), Expr 'BoolSort)]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
forall (m :: * -> *) a. Monad m => [m a] -> m [a]
sequence ([m ((a, b), Expr 'BoolSort)] -> m [((a, b), Expr 'BoolSort)])
-> [m ((a, b), Expr 'BoolSort)] -> m [((a, b), Expr 'BoolSort)]
forall a b. (a -> b) -> a -> b
$ do
(a, b)
i <- ((a, b), (a, b)) -> [(a, b)]
forall a. Ix a => (a, a) -> [a]
A.range ((a, b), (a, b))
bnd
m ((a, b), Expr 'BoolSort) -> [m ((a, b), Expr 'BoolSort)]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return (m ((a, b), Expr 'BoolSort) -> [m ((a, b), Expr 'BoolSort)])
-> m ((a, b), Expr 'BoolSort) -> [m ((a, b), Expr 'BoolSort)]
forall a b. (a -> b) -> a -> b
$ do
Expr 'BoolSort
x <- (a, b) -> m (Expr 'BoolSort)
p (a, b)
i
((a, b), Expr 'BoolSort) -> m ((a, b), Expr 'BoolSort)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ((a, b)
i, Expr 'BoolSort
x)
Relation a b -> m (Relation a b)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Relation a b -> m (Relation a b))
-> Relation a b -> m (Relation a b)
forall a b. (a -> b) -> a -> b
$ ((a, b), (a, b)) -> [((a, b), Expr 'BoolSort)] -> Relation a b
forall a b.
(Ix a, Ix b) =>
((a, b), (a, b)) -> [((a, b), Expr 'BoolSort)] -> Relation a b
build ((a, b), (a, b))
bnd [((a, b), Expr 'BoolSort)]
pairs
identity :: (Ix a)
=> ((a,a),(a,a))
-> Relation a a
identity :: forall a. Ix a => ((a, a), (a, a)) -> Relation a a
identity ((a
a,a
b),(a
c,a
d))
| (a
a,a
c) (a, a) -> (a, a) -> Bool
forall a. Eq a => a -> a -> Bool
== (a
b,a
d) = ((a, a), (a, a)) -> ((a, a) -> Expr 'BoolSort) -> Relation a a
forall a b.
(Ix a, Ix b) =>
((a, b), (a, b)) -> ((a, b) -> Expr 'BoolSort) -> Relation a b
buildFrom ((a
a,a
b),(a
c,a
d)) (\ (a
i,a
j) -> Bool -> Expr 'BoolSort
forall b. Boolean b => Bool -> b
bool (Bool -> Expr 'BoolSort) -> Bool -> Expr 'BoolSort
forall a b. (a -> b) -> a -> b
$ a
i a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
j)
| Bool
otherwise = [Char] -> Relation a a
forall a. HasCallStack => [Char] -> a
error [Char]
"The domain must equal the codomain!"
bounds :: Relation a b -> ((a,b),(a,b))
bounds :: forall a b. Relation a b -> ((a, b), (a, b))
bounds (Relation Array (a, b) (Expr 'BoolSort)
r) = Array (a, b) (Expr 'BoolSort) -> ((a, b), (a, b))
forall i e. Array i e -> (i, i)
A.bounds Array (a, b) (Expr 'BoolSort)
r
{-# INLINE bounds #-}
indices :: (Ix a, Ix b) => Relation a b -> [(a, b)]
indices :: forall a b. (Ix a, Ix b) => Relation a b -> [(a, b)]
indices (Relation Array (a, b) (Expr 'BoolSort)
r) = Array (a, b) (Expr 'BoolSort) -> [(a, b)]
forall i e. Ix i => Array i e -> [i]
A.indices Array (a, b) (Expr 'BoolSort)
r
{-# INLINE indices #-}
assocs :: (Ix a, Ix b) => Relation a b -> [((a, b), Expr BoolSort)]
assocs :: forall a b.
(Ix a, Ix b) =>
Relation a b -> [((a, b), Expr 'BoolSort)]
assocs (Relation Array (a, b) (Expr 'BoolSort)
r) = Array (a, b) (Expr 'BoolSort) -> [((a, b), Expr 'BoolSort)]
forall i e. Ix i => Array i e -> [(i, e)]
A.assocs Array (a, b) (Expr 'BoolSort)
r
{-# INLINE assocs #-}
elems :: Relation a b -> [Expr BoolSort]
elems :: forall a b. Relation a b -> [Expr 'BoolSort]
elems (Relation Array (a, b) (Expr 'BoolSort)
r) = Array (a, b) (Expr 'BoolSort) -> [Expr 'BoolSort]
forall i e. Array i e -> [e]
A.elems Array (a, b) (Expr 'BoolSort)
r
{-# INLINE elems #-}
(!?) :: (Ix a, Ix b) => Relation a b -> (a, b) -> Maybe (Expr BoolSort)
Relation Array (a, b) (Expr 'BoolSort)
r !? :: forall a b.
(Ix a, Ix b) =>
Relation a b -> (a, b) -> Maybe (Expr 'BoolSort)
!? (a, b)
p = Array (a, b) (Expr 'BoolSort)
rArray (a, b) (Expr 'BoolSort)
-> Getting
(First (Expr 'BoolSort))
(Array (a, b) (Expr 'BoolSort))
(Expr 'BoolSort)
-> Maybe (Expr 'BoolSort)
forall s a. s -> Getting (First a) s a -> Maybe a
^?Index (Array (a, b) (Expr 'BoolSort))
-> Traversal'
(Array (a, b) (Expr 'BoolSort))
(IxValue (Array (a, b) (Expr 'BoolSort)))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix (a, b)
Index (Array (a, b) (Expr 'BoolSort))
p
{-# INLINE (!?) #-}
(!) :: (Ix a, Ix b) => Relation a b -> (a, b) -> Expr BoolSort
Relation Array (a, b) (Expr 'BoolSort)
r ! :: forall a b.
(Ix a, Ix b) =>
Relation a b -> (a, b) -> Expr 'BoolSort
! (a, b)
p = Array (a, b) (Expr 'BoolSort)
r Array (a, b) (Expr 'BoolSort) -> (a, b) -> Expr 'BoolSort
forall i e. Ix i => Array i e -> i -> e
A.! (a, b)
p
{-# INLINE (!) #-}
domain :: Ix a => Relation a b -> [a]
domain :: forall a b. Ix a => Relation a b -> [a]
domain Relation a b
r =
let ((a
x,b
_),(a
x',b
_)) = Relation a b -> ((a, b), (a, b))
forall a b. Relation a b -> ((a, b), (a, b))
bounds Relation a b
r
in (a, a) -> [a]
forall a. Ix a => (a, a) -> [a]
A.range (a
x,a
x')
{-# INLINE domain #-}
codomain :: Ix b => Relation a b -> [b]
codomain :: forall b a. Ix b => Relation a b -> [b]
codomain Relation a b
r =
let ((a
_,b
y),(a
_,b
y')) = Relation a b -> ((a, b), (a, b))
forall a b. Relation a b -> ((a, b), (a, b))
bounds Relation a b
r
in (b, b) -> [b]
forall a. Ix a => (a, a) -> [a]
A.range (b
y,b
y')
{-# INLINE codomain #-}
image :: (Ix a, Ix b) => Relation a b -> a -> [Expr BoolSort]
image :: forall a b. (Ix a, Ix b) => Relation a b -> a -> [Expr 'BoolSort]
image Relation a b
r a
x = (b -> Maybe (Expr 'BoolSort)) -> [b] -> [Expr 'BoolSort]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe ((Relation a b
r !?) ((a, b) -> Maybe (Expr 'BoolSort))
-> (b -> (a, b)) -> b -> Maybe (Expr 'BoolSort)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a
x,)) (Relation a b -> [b]
forall b a. Ix b => Relation a b -> [b]
codomain Relation a b
r)
{-# INLINE image #-}
preimage :: (Ix a, Ix b) => Relation a b -> b -> [Expr BoolSort]
preimage :: forall a b. (Ix a, Ix b) => Relation a b -> b -> [Expr 'BoolSort]
preimage Relation a b
r b
y = (a -> Maybe (Expr 'BoolSort)) -> [a] -> [Expr 'BoolSort]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe ((Relation a b
r !?) ((a, b) -> Maybe (Expr 'BoolSort))
-> (a -> (a, b)) -> a -> Maybe (Expr 'BoolSort)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (,b
y)) (Relation a b -> [a]
forall a b. Ix a => Relation a b -> [a]
domain Relation a b
r)
{-# INLINE preimage #-}
table :: (Ix a, Ix b)
=> Array (a,b) Bool -> String
table :: forall a b. (Ix a, Ix b) => Array (a, b) Bool -> [Char]
table Array (a, b) Bool
r = [[Char]] -> [Char]
unlines ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$ do
let ((a
a,b
b),(a
c,b
d)) = Array (a, b) Bool -> ((a, b), (a, b))
forall i e. Array i e -> (i, i)
A.bounds Array (a, b) Bool
r
a
x <- (a, a) -> [a]
forall a. Ix a => (a, a) -> [a]
A.range (a
a,a
c)
[Char] -> [[Char]]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Char] -> [[Char]]) -> [Char] -> [[Char]]
forall a b. (a -> b) -> a -> b
$ [[Char]] -> [Char]
unwords ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$ do
b
y <- (b, b) -> [b]
forall a. Ix a => (a, a) -> [a]
A.range (b
b,b
d)
[Char] -> [[Char]]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Char] -> [[Char]]) -> [Char] -> [[Char]]
forall a b. (a -> b) -> a -> b
$ if Array (a, b) Bool
r Array (a, b) Bool -> (a, b) -> Bool
forall i e. Ix i => Array i e -> i -> e
A.! (a
x,b
y) then [Char]
"*" else [Char]
"."