Haskell ADTs depending on each other - haskell

Hi I'm trying to write a proof checker in Haskell. One way of representing terms is as follows:
data Term = Const String | Fun String [Term] | Var String
But this seems unideal, since String can take on many values and there is no way of verifying the arity of function terms.
One solution is as follows:
data Term a = Const String | Fun a | Var String
data NTFun = S (Term NTFun) | Plus (Term NTFun) (Term NTFun)
type NTTerm = Term NTFun
Now I have a more generic Term type and can instantiate it as I please. But if I want to abstract out constant symbols as well it gets messy.
data Term a c = Const c | Fun a | Var String
data NTFun c = S (Term c (NTFun c)) | Plus (Term c (NTFun c)) (Term c (NTFun c))
data NTConst = Zero
type NTTerm = Term (NTFun NTConst) NTConst
It seems there must be a better way to express this? Thanks!

You can change NTFun to be a functor, abstracting out its mentions of Term and any of its other variables, and have Term itself tie the knot.
data Term f c = Const c | Fun (f (Term f c)) | Var String
data NTFun term = S term | Plus term term
data NTConst = Zero
type NTTerm = Term NTFun NTConst

Related

How to create a data type containing a list

I'm trying to create a data type class that contains a list:
data Test = [Int] deriving(Show)
But Haskell can't parse the constructor. What am i doing wrong here and how can I best achieve what I'm trying to do?
An Answer
You need to include a constructor, which you haven't done.
data Test = Test [Int]
Consider reviewing Haskell's several type declarations, their use, and their syntax.
Haskell Type Declarations
data
Allows declaration of zero or more constructors each with zero or more fields.
newtype
Allows declaration of one constructor with one field. This field is strict.
type
Allows creation of a type alias which can be textually interchanged with the type to the right of the equals at any use.
constructor
Allows creation of a value of the declared type. Also allows decomposition of values to obtain the individual fields (via pattern matching)
Examples
data
data Options = OptionA Int | OptionB Integer | OptionC PuppyAges
^ ^ ^ ^ ^ ^ ^
| | Field | | | |
type Constructor | | Constructor |
Constructor Field Field
deriving (Show)
myPuppies = OptionB 1234
newtype
newtype PuppyAges = AgeList [Int] deriving (Show)
myPuppies :: PuppyAges
myPuppies = AgeList [1,2,3,4]
Because the types (PuppyAges) and the constructors (AgeList) are in different namespaces people can and often do use the same name for each, such as newtype X = X [Int].
type
type IntList = [Int]
thisIsThat :: IntList -> [Int]
thisIsThat x = x
constructors (more)
option_is_a_puppy_age :: Options -> Bool
option_is_a_puppy_age (OptionC _) = True
option_is_a_puppy_age () = False
option_has_field_of_value :: Options -> Int -> Bool
option_has_field_of_value (OptionA a) x = x == a
option_has_field_of_value (OptionB b) x = fromIntegral x == b
option_has_field_of_value (OptionC (AgeList cs)) x = x `elem` cs
increment_option_a :: Options -> Options
increment_option_a (OptionA a) = OptionA (a+1)
increment_option_a x = x

Type casting when working with nested data structures

I have the following data structures defined:
data Operator = Plus | Times | Minus deriving (Eq,Show)
data Variable = A | B | C deriving (Eq,Show)
newtype Const = D Numeral deriving (Eq,Show)
data CVO = Const | Variable | Operator deriving (Eq,Show)
type Expr = [CVO]
I have defined the following function:
eval2 :: Expr -> Integer
eval2 x = helper x
I would like to check if an element of the CVO list (Expr) is either an instance of Const, Variable or Operator (this works) and I would like to implement varying code for the specific type of the instance (e.g. Plus, Times, Minus for Operator).
helper :: Expr -> Integer
helper [] = 2
helper (x:xs)
| x == Operator && x == Plus = 1
I cannot compare x to Plus, because it expects x to be of type CVO.
Couldn't match expected type ‘CVO’ with actual type ‘Operator’
Is it somehow possible to cast x to be an instance of Operator in order to do the comparison?
A value can't have two different types at the same time. If x is a CVO you can't use == to compare it to Plus which is an Operator.
At the moment the type CVO consists of three constant values called Const, Variable and Operator. I'm guessing you actually wanted it to contain values of the type Const, Variable or Operator. You do that by declaring arguments to the constructors.
data CVO = Const Const -- a constructor whose name is Const and contains a value of type Const
| Var Variable -- a constructor named Var containing a Variable
| Op Operator -- a constructor named Op containing an Operator
A given value of type CVO must have been built from one of those three constructors, containing a value of the correct type. You can test which constructor was used to create the CVO, and simultaneously unpack the value, using pattern matching. Something like this:
helper :: Expr -> Integer
helper [] = 0
helper (Op o:xs) -- because we matched Op, we know o :: Operator
| o == Plus = 1
| otherwise = 2
helper _ = 3

Haskell Type Destructuring in Guards

I'm playing around with a toy project in Haskell. I'm implementing some data structures I've built in other languages before to familiarize myself with how they'd be built in Haskell. This isn't my first functional language, I've built a couple of projects like a Scheme interpreter in OCaml but I think my OCaml experience is coloring how I'm approaching this problem. Its' not terribly important, but may be useful for context, to know that the data structure I'm implementing is a PR-Quadtree.
What I want to do is match and destructure a type inside a guard, a la OCaml's match statement.
data Waypoint = WayPoint {
lat :: Float,
lon :: Float,
radius :: Float,
speed :: Float,
accel :: Float
} deriving (Show)
data Region = Region {
x :: Float,
y :: Float,
width :: Float
} deriving (Show)
data PRQuadtree = WhiteNode Region
| BlackNode Region Waypoint
| GreyNode {
topLeft :: PRQuadtree,
topRight :: PRQuadtree,
botLeft :: PRQuadtree,
botRight :: PRQuadtree,
region :: Region
} deriving (Show)
getRegion node
| BlackNode(r, _) = r
| WhiteNode(r) = r
| GreyNode = region node
The getRegion function is the one I am having problems with in particular. In case what I'm trying to do is unclear: I'd like to simple extract one element of the argument but that depends on which member of the algebraic data type the argument is. In OCaml I could do:
let getRegion node = match node with
| BlackNode(r, _) = r
| WhiteNode(r) = r
| GreyNode = region(node)
(or something very similar, my OCaml is a bit rusty now).
In Haskell however, this doesn't appear to bind r in scope of the RHS of the guard branch. I've tried to look up Pattern Guards, as they sound similar to what I might want to do, but I can't really grok whats going on here. Really I just want to get a binding from the LHS of the = to the RHS of the equals (depending on which branch of the guard we've gone down).
Whats the idiomatic Haskell way to do what I'm trying to do here?
It can be achieved as follows:
getRegion :: PRQuadtree -> Region
getRegion (BlackNode r _) = r
getRegion (WhiteNode r) = r
getRegion GreyNode{region=r} = r
or even as
getRegion :: PRQuadtree -> Region
getRegion x = case x of
BlackNode r _ -> r
WhiteNode r -> r
GreyNode{} -> region x
In Haskell, prepending a type signature is very idiomatic.
Another option is extending the region field to the other cases as well:
data PRQuadtree = WhiteNode { region :: Region }
| BlackNode { region :: Region , waypoint :: Waypoint }
| GreyNode {
topLeft :: PRQuadtree,
topRight :: PRQuadtree,
botLeft :: PRQuadtree,
botRight :: PRQuadtree,
region :: Region
} deriving (Show)
Now, region will work on all PRQuadtree values.
Haskell uses | as ML does when defining algebraic datatypes, to separate different constructors, but does not use it to separate case branches, which instead follow the syntax
case .. of { pat1 -> e1 ; pat2 -> e2 ; ... }
which can be replaced by indentation
case .. of
pat1 -> e1
pat2 -> e2
...
Also, note that partial field selectors are discouraged:
data A = A1 { foo :: Int } | A2
Above, foo A2 type checks but crashes. On the other hand, when a field is present in all the constructors, we do not face such risk.
You can also write:
getRegion x
| BlackNode y <- x -> ....
| Greynode{} <- x -> ....
but it is quite unidiomatic in this simple case.
However, in more complex programs, this pattern matching in guards can be very useful. You use multiple equations or case to distinguish the general cases, like shown by #chi. But then, you can detect special cases, like in the following made up example:
getRegion x = case x of
BlackNode{region}
| [(0,_)] <- filter (inRegion region) interestingPoints
-> -- region encloses exactly 1 interesting point on x axis
....
| otherwise = ....
where
interestingPoints = .....
inRegion :: Region -> Point -> Bool
GreyNode{} -> ....

Haskell: Iterating through material in a (complex, recursive) ADT _with context_

I have an ADT for, basically, first order logic:
data Function = Function String
data Predicate = Predicate String
data Type_ = TPoint | TSet | TFunction | TPositiveRealNumber | TSequence | TNaturalNumber | TGroup
data VariableType = VTNormal | VTDiamond | VTBullet
data Dependencies = Dependencies [Term] {-dep-} [Term] {-indep-}
data Variable = Variable String Int Type_ VariableType Dependencies
data Term = VariableTerm Variable
| ApplyFn Function [Term]
data Formula = AtomicFormula Predicate [Term]
| Not Formula
| And [Formula]
| Or [Formula]
| Forall [Variable] Formula
| UniversalImplies [Variable] [Formula] Formula
| Exists [Variable] Formula
And I need to iterate through each Term (potentially deeply) nested inside a given Formula and do something to it -- said thing will depend on both the term and the 'context' in which it appears. So as a simple example we could print out the formula repeatedly, with each copy having a different term bolded. I don't want this particular behavior wired in; I want a higher-order function with the following type signature
f :: (FormulaWithTermShapedHole -> Term -> a) -> Formula -> [a]
I already have a function with this type signature which can do something to every term...
mapTermInFormulaM :: Monad m => (Term -> m Term) -> Formula -> m Formula
... but it can't utilise context in the way I now need. (So it could print every term that occurs somewhere inside the formula, but it couldn't print the whole formula with the term bolded.)
It feels like there should be a slick way of doing this... any suggestions would be welcome.
This can be done with generic programming in Haskell.
A good starting point for this is:
http://www.haskell.org/haskellwiki/Scrap_your_boilerplate
And there are some excellent papers by Simon Peyton Jones who started this, if you want to read further:
http://research.microsoft.com/en-us/um/people/simonpj/papers/hmap/

Recursive data structures in haskell: prolog-like terms

I have a question about recursive data structures in Haskell (language that I'm currently trying to learn).
I would like to encode in Haskell Prolog-like terms, but every solution I came up with has different drawbacks that I would really like to avoid. I would like to find a cheap and elegant way of encoding a BNF grammar in Haskell types, if you wish to see my problem from this perspective.
Just as a reminder, some prolog terms could be male, sum(2, 3.1, 5.1), btree(btree(0, 1), Variable).
Solution 1
data Term = SConst String
| IConst Integer
| FConst Double
| Var String
| Predicate {predName :: String, predArgs :: [Term]}
With this solution I can have nested predicates (since predArgs are Term), but I can't distinguish predicates from other terms in type signatures.
Solution 2
data Term = SConst String
| IConst Integer
| FConst Double
| Var String
data Predicate = Predicate {predName :: String, predArgs ::[Either Term Predicate}
In this variant I can clearly distinguish predicates from basic terms, but the Either type in the predArgs list can be quite a nuisance to manage later in the code (I think... I'm new to Haskell).
Solution 3
data Term = SConst String
| IConst Integer
| FConst Double
| Var String
| Struct String [Term]
data Predicate = Predicate String [Term]
With this last solution, I split terms in two different types as before, but this time I avoid Either Term Predicate adding a Struct constructor in Term with basically the same semantics as Predicate.
It's just like solution 1 with two predicate constructors for terms. One is recursion-enabled, Struct, and the other one, Predicate is to be able to distinguish between predicates and regular terms.
The problem with this try is that Struct and Predicate are structurally equivalent and have almost the same meaning, but I will not be able to write functions that works - in example - both on (Predicate "p" []) and (Struct "p" []).
So again my question is: please, is there a better way to encode my predicates and terms such that:
I'm able to distinguish between predicate and terms in type signatures;
nested predicates like p(q(1), r(q(3), q(4))) are supported;
I can write functions that will work uniformly on predicates, without any
distinction like the one in solution #3?
Please feel free to ask me for further clarifications should you need any.
Thank you very much.
You could add a term constructor to wrap a predicate. Here, I also factored all of the literals into their own data type:
data Term = TLit Literal
| TVar String
| TPred Predicate
data Literal = LitS String
| LitI Int
| LitF Double
data Predicate = Predicate String [Term]
Here's one way (that's probably not worth the trouble):
{-# LANGUAGE EmptyDataDecls #-}
-- 'T' and 'F' are short for 'True' and 'False'
data T = T
data F
-- 'p' is short for 'mayNotBeAPredicate'
data Term p
= SConst !p String
| IConst !p Integer
| FConst !p Double
| Var !p String
| Predicate {predName :: String, predArgs :: [Term T]}
sconst :: String -> Term T
iconst :: Integer -> Term T
fconst :: Double -> Term T
var :: String -> Term T
predicate :: String -> [Term T] -> Term p
sconst = SConst T
iconst = IConst T
fconst = FConst T
var = Var T
predicate = Predicate
checkPredicate :: Term p -> Maybe (Term F)
checkPredicate (Predicate name args) = Just (Predicate name args)
checkPredicate _ = Nothing
forgetPredicate :: Term p -> Term T
forgetPredicate (SConst _ s) = sconst s
forgetPredicate (IConst _ i) = iconst i
forgetPredicate (FConst _ f) = fconst f
forgetPredicate (Var _ s) = var s
forgetPredicate (Predicate name args) = predicate name args
You can now write functions which only accept predicates by giving them an input type of Term F, and functions which accept any input type by giving them an input type of Term p.

Resources