Disclaimer: I am new to working with haskell.
I am working with proving logical formulas in haskell. I have trouble understanding how to work with newtype
s and data
s properly.
I have defined the following types to represent logical formulas that have the structure: (a or b or c) and (d or e) and (f)
etc.
data Literal x = Literal x | Negation x
deriving (Show, Eq)
newtype Or x = Or [Literal x]
deriving (Show, Eq)
newtype And x = And [Or x]
deriving (Show, Eq)
I want to write a function that can filter on the literals (i.e. take out certain a
b
or c
based on some condition). Naively I thought this should be similar to filtering on [[Literal x]]
but I cannot seem to get it to work.
My current method is something like:
filterLit :: Eq x => And x -> And x
filterLit = map (\(Or x) -> (filter (\(Lit l) -> condition l) x))
This doesn't type. I feel like I'm missing some syntax rules here. Let me know if you have suggestions on how I should approach it.
CodePudding user response:
\(Or x) -> filter (\(Lit l) -> condition l) x
Let's check the type of this function.
The domain must have type Or x
. That's OK.
The codomain is the result of filter
, hence it is a list. Let's only write [....]
for that.
Hence, the function is Or x -> [....]
.
If we map
that, we get [Or x] -> [[....]]
. This is not the same as the claimed type And x -> And x
-- a type error is raised.
First, you want your lambda to have type Or x -> Or x
. For that, you can use \(Or x) -> Or (filter .....)
.
Then, you want filterLit
to be something like
filterLit (And ys) = And (map ....)
so that it has the right type.