Grisette – How do I implement functions that operate on `UnionM [UnionM SymInteger]`?

  Kiến thức lập trình

Let me first explain my understanding of why we need this monstrosity. Essentially, I want to work on lists of SymInteger. But, AFAIU, you need to wrap a SymInteger into a UnionM whenever the result of an operation is not a simple value (like 2 or "a") and it is e.g., a condition (e.g., the result of mrgIf).

Now, suppose we want to create a function that takes two [SymInteger] and returns a [SymInteger] that has the element-wise maximum of the two lists. We cannot do the following:

pickLargest :: [SymInteger] -> [SymInteger] -> [SymInteger]
-- skip simple cases
pickLargest (x:xs) (y:ys) = (mrgIf (x .> y) x y) : (sumSym xs ys)

because mrgIf returns UnionM SymInteger and not SymInteger. So, we need [UnionM SymInteger] for our functions to be generic, like so:

pickLargest :: [UnionM SymInteger] -> [UnionM SymInteger] -> [UnionM SymInteger]
-- ...
pickLargest (x:xs) (y:ys) = (mrgIf (x .> y) x y) : (pickLargest xs ys)

Now, suppose that I also want to create a function that drops an element from a list, if it exists. I can’t use symDrop because that takes a SymInteger and not a UnionM SymInteger. So, the following won’t work:

myVar :: [UnionM SymInteger]
myVar = pickLargest ["a", "b"] ["c", "d"]

dropOnSym = print (symDrop (head myVar) myVar)

because head myVar has type UnionM SymInteger (and AFAIU, it will also not work
if I want to call symDrop on the result of symDrop). Finally, because we don’t know the length of the resulting list, it makes sense that it needs to be wrapped in a UnionM.

Thus, the only way to implement symListDrop I’ve found is this:

symListDrop :: UnionM [UnionM SymInteger] -> UnionM SymInteger -> UnionM [UnionM SymInteger]
symListDrop m_ser m_el = do
  ser <- m_ser
  case ser of
    [] -> mrgReturn []
    (x:_) -> mrgIf (x .== m_el) 
                (symListDrop m_ser m_el)
                (mrgBind (symListDrop m_ser m_el) (ys -> mrgReturn (x : ys)))

which I’m afraid is just me trying really really hard… In particular, the fact that I have to unpack the UnionM seems suspicious.

So, do you have a suggestion on how to implement this function, or alternatively, a different way that these problems are supposed to be modeled?

LEAVE A COMMENT