How to limit a Int field to a range of values? - haskell

In my Data
data User = User { uRank :: Int, uProgress :: Int }
I want to limit uRank to a list of values [-1, 1, 3], for example.
How do I do this?

Defining a small sum type is the best answer for this specific question. You can also use newtype with smart constructors to achieve this effect.
newtype Rank = UnsafeMkRank { unRank :: Int }
mkRank :: Int -> Maybe Rank
mkRank i
| i `elem` [-1, 1, 3] = Just (UnsafeMkRank i)
| otherwise = Nothing
Now, provided you only use the safe mkRank constructor, you can assume that your Rank values have the Int values you want.

For something so small, you should define a precise type:
data Rank = RankNegOne | RankOne | RankThree -- There are probably better names
data User = User { uRank :: Rank, uProgress :: Int }
Haskell doesn't force you to encode everything as a subset of the integers; take advantage of it!
For larger subsets where this would be unwieldy, you are looking for a dependent type, which (until recently?) is not supported by Haskell directly.

Liquid Haskell, which adds refinement types on top of Haskell, can do this. See the correct section of the tutorial here.
First you define your data type as normal.
module User where
data User = User { uRank :: Int
, uProgress :: Int
}
Next we define your restriction as a refinement type. Liquid Haskell users comment annotations with syntax {-# blah #-}. We'll define your odd restriction of -1, 1, 3 first with the RestrictedInt type:
{-# type RestrictedInt = {v : Int | v == -1 || v == 1 || v == 3} #-}
That is, the RestrictedInt is an Int that is either -1, 1, or 3. Notice you could easily write ranges and other restrictions, it doesn't have to be some mindless enumeration of legitimate values.
Now we re-define your data type in our refinement language using this restricted int type:
{-# data User = User { uRank :: RestrictedInt
, uProgress :: Int }
#-}
This is similar to your definition but with the restriction type instead of just Int. We could have inlined the restriction instead of having a type alias but then your User data type would be pretty unreadable.
You can define good values and the liquid tool will not complain:
goodValue :: User
goodValue = User 1 12
But bad values result in an error:
badValue :: User
badValue = User 10 12
$ liquid so.hs (or your editor's integration, if you have that setup) produces:
**** RESULT: UNSAFE ************************************************************
so.hs:16:12-18: Error: Liquid Type Mismatch
16 | badValue = User 10 12
^^^^^^^
Inferred type
VV : {VV : GHC.Types.Int | VV == ?a}
not a subtype of Required type
VV : {VV : GHC.Types.Int | VV == (-1)
|| (VV == 1
|| VV == 3)}
In Context
?a := {?a : GHC.Types.Int | ?a == (10 : int)}

Related

Clarifying Data Constructor in Haskell

In the following:
data DataType a = Data a | Datum
I understand that Data Constructor are value level function. What we do above is defining their type. They can be function of multiple arity or const. That's fine. I'm ok with saying Datum construct Datum. What is not that explicit and clear to me here is somehow the difference between the constructor function and what it produce. Please let me know if i am getting it well:
1 - a) Basically writing Data a, is defining both a Data Structure and its Constructor function (as in scala or java usually the class and the constructor have the same name) ?
2 - b) So if i unpack and make an analogy. With Data a We are both defining a Structure(don't want to use class cause class imply a type already i think, but maybe we could) of object (Data Structure), the constructor function (Data Constructor/Value constructor), and the later return an object of that object Structure. Finally The type of that Structure of object is given by the Type constructor. An Object Structure in a sense is just a Tag surrounding a bunch value of some type. Is my understanding correct ?
3 - c) Can I formally Say:
Data Constructor that are Nullary represent constant values -> Return the the constant value itself of which the type is given by the Type Constructor at the definition site.
Data Constructor that takes an argument represent class of values, where class is a Tag ? -> Return an infinite number of object of that class, of which the type is given by the Type constructor at the definition site.
Another way of writing this:
data DataType a = Data a | Datum
Is with generalised algebraic data type (GADT) syntax, using the GADTSyntax extension, which lets us specify the types of the constructors explicitly:
{-# LANGUAGE GADTSyntax #-}
data DataType a where
Data :: a -> DataType a
Datum :: DataType a
(The GADTs extension would work too; it would also allow us to specify constructors with different type arguments in the result, like DataType Int vs. DataType Bool, but that’s a more advanced topic, and we don’t need that functionality here.)
These are exactly the types you would see in GHCi if you asked for the types of the constructor functions with :type / :t:
> :{
| data DataType a where
| Data :: a -> DataType a
| Datum :: DataType a
| :}
> :type Data
Data :: a -> DataType a
> :t Datum
Datum :: DataType a
With ExplicitForAll we can also specify the scope of the type variables explicitly, and make it clearer that the a in the data definition is a separate variable from the a in the constructor definitions by also giving them different names:
data DataType a where
Data :: forall b. b -> DataType b
Datum :: forall c. DataType c
Some more examples of this notation with standard prelude types:
data Either a b where
Left :: forall a b. a -> Either a b
Right :: forall a b. b -> Either a b
data Maybe a where
Nothing :: Maybe a
Just :: a -> Maybe a
data Bool where
False :: Bool
True :: Bool
data Ordering where
LT, EQ, GT :: Ordering -- Shorthand for repeated ‘:: Ordering’
I understand that Data Constructor are value level function. What we do above is defining their type. They can be function of multiple arity or const. That's fine. I'm ok with saying Datum construct Datum. What is not that explicit and clear to me here is somehow the difference between the constructor function and what it produce.
Datum and Data are both “constructors” of DataType a values; neither Datum nor Data is a type! These are just “tags” that select between the possible varieties of a DataType a value.
What is produced is always a value of type DataType a for a given a; the constructor selects which “shape” it takes.
A rough analogue of this is a union in languages like C or C++, plus an enumeration for the “tag”. In pseudocode:
enum Tag {
DataTag,
DatumTag,
}
// A single anonymous field.
struct DataFields<A> {
A field1;
}
// No fields.
struct DatumFields<A> {};
// A union of the possible field types.
union Fields<A> {
DataFields<A> data;
DatumFields<A> datum;
}
// A pair of a tag with the fields for that tag.
struct DataType<A> {
Tag tag;
Fields<A> fields;
}
The constructors are then just functions returning a value with the appropriate tag and fields. Pseudocode:
<A> DataType<A> newData(A x) {
DataType<A> result;
result.tag = DataTag;
result.fields.data.field1 = x;
return result;
}
<A> DataType<A> newDatum() {
DataType<A> result;
result.tag = DatumTag;
// No fields.
return result;
}
Unions are unsafe, since the tag and fields can get out of sync, but sum types are safe because they couple these together.
A pattern-match like this in Haskell:
case someDT of
Datum -> f
Data x -> g x
Is a combination of testing the tag and extracting the fields. Again, in pseudocode:
if (someDT.tag == DatumTag) {
f();
} else if (someDT.tag == DataTag) {
var x = someDT.fields.data.field1;
g(x);
}
Again this is coupled in Haskell to ensure that you can only ever access the fields if you have checked the tag by pattern-matching.
So, in answer to your questions:
1 - a) Basically writing Data a, is defining both a Data Structure and its Constructor function (as in scala or java usually the class and the constructor have the same name) ?
Data a in your original code is not defining a data structure, in that Data is not a separate type from DataType a, it’s just one of the possible tags that a DataType a value may have. Internally, a value of type DataType Int is one of the following:
The tag for Data (in GHC, a pointer to an “info table” for the constructor), and a reference to a value of type Int.
x = Data (1 :: Int) :: DataType Int
+----------+----------------+ +---------+----------------+
x ---->| Data tag | pointer to Int |---->| Int tag | unboxed Int# 1 |
+----------+----------------+ +---------+----------------+
The tag for Datum, and no other fields.
y = Datum :: DataType Int
+-----------+
y ----> | Datum tag |
+-----------+
In a language with unions, the size of a union is the maximum of all its alternatives, since the type must support representing any of the alternatives with mutation. In Haskell, since values are immutable, they don’t require any extra “padding” since they can’t be changed.
It’s a similar situation for standard data types, e.g., a product or sum type:
(x :: X, y :: Y) :: (X, Y)
+---------+--------------+--------------+
| (,) tag | pointer to X | pointer to Y |
+---------+--------------+--------------+
Left (m :: M) :: Either M N
+-----------+--------------+
| Left tag | pointer to M |
+-----------+--------------+
Right (n :: N) :: Either M N
+-----------+--------------+
| Right tag | pointer to N |
+-----------+--------------+
2 - b) So if i unpack and make an analogy. With Data a We are both defining a Structure(don't want to use class cause class imply a type already i think, but maybe we could) of object (Data Structure), the constructor function (Data Constructor/Value constructor), and the later return an object of that object Structure. Finally The type of that Structure of object is given by the Type constructor. An Object Structure in a sense is just a Tag surrounding a bunch value of some type. Is my understanding correct ?
This is sort of correct, but again, the constructors Data and Datum aren’t “data structures” by themselves. They’re just the names used to introduce (construct) and eliminate (match) values of type DataType a, for some type a that is chosen by the caller of the constructors to fill in the forall
data DataType a = Data a | Datum says:
If some term e has type T, then the term Data e has type DataType T
Inversely, if some value of type DataType T matches the pattern Data x, then x has type T in the scope of the match (case branch or function equation)
The term Datum has type DataType T for any type T
3 - c) Can I formally Say:
Data Constructor that are Nullary represent constant values -> Return the the constant value itself of which the type is given by the Type Constructor at the definition site.
Data Constructor that takes an argument represent class of values, where class is a Tag ? -> Return an infinite number of object of that class, of which the type is given by the Type constructor at the definition site.
Not exactly. A type constructor like DataType :: Type -> Type, Maybe :: Type -> Type, or Either :: Type -> Type -> Type, or [] :: Type -> Type (list), or a polymorphic data type, represents an “infinite” family of concrete types (Maybe Int, Maybe Char, Maybe (String -> String), …) but only in the same way that id :: forall a. a -> a represents an “infinite” family of functions (id :: Int -> Int, id :: Char -> Char, id :: String -> String, …).
That is, the type a here is a parameter filled in with an argument value given by the caller. Usually this is implicit, through type inference, but you can specify it explicitly with the TypeApplications extension:
-- Akin to: \ (a :: Type) -> \ (x :: a) -> x
id :: forall a. a -> a
id x = x
id #Int :: Int -> Int
id #Int 1 :: Int
Data :: forall a. a -> DataType a
Data #Char :: Char -> DataType Char
Data #Char 'x' :: DataType Char
The data constructors of each instantiation don’t really have anything to do with each other. There’s nothing in common between the instantiations Data :: Int -> DataType Int and Data :: Char -> DataType Char, apart from the fact that they share the same tag name.
Another way of thinking about this in Java terms is with the visitor pattern. DataType would be represented as a function that accepts a “DataType visitor”, and then the constructors don’t correspond to separate data types, they’re just the methods of the visitor which accept the fields and return some result. Writing the equivalent code in Java is a worthwhile exercise, but here it is in Haskell:
{-# LANGUAGE RankNTypes #-}
-- (Allows passing polymorphic functions as arguments.)
type DataType a
= forall r. -- A visitor with a generic result type
r -- With one “method” for the ‘Datum’ case (no fields)
-> (a -> r) -- And one for the ‘Data’ case (one field)
-> r -- Returning the result
newData :: a -> DataType a
newData field = \ _visitDatum visitData -> visitData field
newDatum :: DataType a
newDatum = \ visitDatum _visitData -> visitDatum
Pattern-matching is simply running the visitor:
matchDT :: DataType a -> b -> (a -> b) -> b
matchDT dt visitDatum visitData = dt visitDatum visitData
-- Or: matchDT dt = dt
-- Or: matchDT = id
-- case someDT of { Datum -> f; Data x -> g x }
-- f :: r
-- g :: a -> r
-- someDT :: DataType a
-- :: forall r. r -> (a -> r) -> r
someDT f (\ x -> g x)
Similarly, in Haskell, data constructors are just the ways of introducing and eliminating values of a user-defined type.
What is not that explicit and clear to me here is somehow the difference between the constructor function and what it produce
I'm having trouble following your question, but I think you are complicating things. I would suggest not thinking too deeply about the "constructor" terminology.
But hopefully the following helps:
Starting simple:
data DataType = Data Int | Datum
The above reads "Declare a new type named DataType, which has the possible values Datum or Data <some_number> (e.g. Data 42)"
So e.g. Datum is a value of type DataType.
Going back to your example with a type parameter, I want to point out what the syntax is doing:
data DataType a = Data a | Datum
^ ^ ^ These things appear in type signatures (type level)
^ ^ These things appear in code (value level stuff)
There's a bit of punning happening here. so in the data declaration you might see "Data Int" and this is mixing type-level and value-level stuff in a way that you wouldn't see in code. In code you'd see e.g. Data 42 or Data someVal.
I hope that helps a little...

Haskell cannot define function as part of record?

I would like to define a data type that is a record with one function named f:
data A = A { f :: Int -> Int }
and I would like to create an instance:
A {f x = x * 2 }
However: this gives a syntax error:
error: parse error on input ‘x’
The following is the grammar for constructions using field labels.
aexp → qcon { fbind1 , … , fbindn } (labeled construction, n ≥ 0)
fbind → qvar = exp
Note that qcon is a constructor syntax, qvar is a variable syntax, and exp is an expression syntax.
The reason A {f x = x * 2} does not work therefore is because it is invalid syntax. A syntax that is valid and that is probably what you want is A {f = \x -> x * 2}. Alternatively, A {f = (* 2)}, A {f = (2 *)}, or A {f = (*) 2}.
Construction using field labels operates like named parameters. Given a data type definition such as
data Person = Person { name :: String, age :: Int }
The expression
Person { age = 65, name = "Wilbur Suidae" }
Means
Person "Wilbur Suidae" 65
That is, the constructor arguments are ordered to match the order of fields according to the constructor definition.
The expression
Person { age = 65 }
Means
Person undefined 65
That is, if a field is not explicitly assigned a value it is implicitly assigned the value undefined.
References
Construction Using Field Labels, § 3.15.2, Haskell Report 2010

LiquidHaskell: Trying to use assume keyword, but data type is not numeric

I'm trying to write some specifications for the Data.Ratio module. So far I have:
module spec Data.Ratio where
import GHC.Real
Data.Ratio.denominator :: GHC.Real.Integral a => r : GHC.Real.Ratio a -> {x:a | x > 0}
The code I'm verifying is:
{-# die :: {v:String | false} -> a #-}
die msg = error msg
main :: IO ()
main = do
let x = 3 % 5
print $ denominator x
if denominator x < 0
then die "bad ending"
else putStrLn "good ending"
The code is judged safe, because denominator never returns a negative value.
I found this strange because I could have just written x <= 0 as a postcondition, which according to the documentation of the Data.Ratio module is impossible. Apparently Liquid Haskell does not compare my postcondition to the implementation of denominator.
My understanding is that since the function implementation was not checked, I'm better off using the assume keyword:
assume Data.Ratio.denominator :: GHC.Real.Integral a => r : GHC.Real.Ratio a -> {x:a | x > 0}
However, I then get:
Error: Bad Type Specification
assumed type GHC.Real.denominator :: (Ratio a) -> {VV : a | VV > 0}
Sort Error in Refinement: {VV : a_a2kc | VV > 0}
Unbound Symbol a_a2kc
Perhaps you meant: papp5, papp3, papp4, head, papp2, papp7, papp6, papp1, tail
because
The sort a_a2kc is not numeric
My questions are
Shouldn't LH force me to use the assume keyword in this case if it clearly didn't verify the correctness of my refined type by comparing with the function implementation?
Am I right in thinking I should use the assume keyword?
How come a is suddenly not numeric? Wasn't it numeric when I didn't use assume?
Unfortunately by 'Numeric' it literally means 'Num' and not even subclasses thereof. We need to extend LH to support sub-classes in the form you describe above; I will create an issue for it, thanks for pointing out!
Now, if you specialize your type to, e.g. Int or Integer then LH properly throws the error:
import GHC.Real
{-# assume denom :: r:GHC.Real.Ratio Int -> {x:Int | x >= 0} #-}
denom :: GHC.Real.Ratio Int -> Int
denom = denominator
{-# die :: {v:String | false} -> a #-}
die msg = error msg
main :: IO ()
main = do
let x = 3 % 5
print $ denom x
if denom x <= 0
then die "bad ending"
else putStrLn "good ending"
http://goto.ucsd.edu:8090/index.html#?demo=permalink%2F1504739852_3583.hs
if you make the output type x > 0 then it is safe again.
http://goto.ucsd.edu:8090/index.html#?demo=permalink%2F1504739907_3585.hs
Thanks again for pointing out the Ratio issue!

Type error when messing up with lenses [duplicate]

This question already has answers here:
Why do 3 and x (which was assigned 3) have different inferred types in Haskell? [duplicate]
(3 answers)
Closed 7 years ago.
I am encountering a type error when trying to compile some lens code.
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens.Setter (over)
import Control.Lens.Getter (view)
import Control.Lens.TH
data IL = IL {
_ilL :: [Int]
}
deriving (Show)
makeLenses ''IL
val = IL [1, 2, 3]
(val1, val2) = let l = ilL
in (over l tail val, view l val)
The error is:
Test.hs:17:35:
Couldn't match expected type `Control.Lens.Internal.Getter.Accessor [Int] [Int]'
with actual type `Control.Lens.Internal.Setter.Mutator [Int]'
Expected type: Control.Lens.Getter.Getting [Int] s0 [Int]
Actual type: ([Int]
-> Control.Lens.Internal.Setter.Mutator [Int])
-> IL -> Control.Lens.Internal.Setter.Mutator IL
In the first argument of `view', namely `l'
In the expression: view l val
This error goes away if I use ilL directly. However, I really need to make a lens definition using let. How can I solve this?
Yet another case of the dreaded monomorphism restriction. Add {-# LANGUAGE NoMonormorphismRestriction #-} at the top of your file and it will compile just fine.
The reason is because when you do let l = ilL in ... without an explicit type signature (or the MR disabled) GHC wants to specialize the type of l as much as it can. It first encounters its use in over l tail val and specializes to the type needed there, but this conflicts with the specialized inferred type in view l val. The solution is to disable the MR or add explicit type signatures like
(val1, val2) =
let l :: Lens' IL [Int]
l = ilL
in (over l tail val, view l val)
This is very similar to a more simple case like
x = let y = 1
z = 2 :: Int
w = 3 :: Double
in (z + y, w + y)
What should the type of y be? With the MR the compiler wants to restrict the type of y to be a single type, but we would really like it to have the type Num a => a since this can work with Ints or Doubles. With the MR turned off the compiler won't specialize the type of y and everything works as expected. The alternative is to give y an explicit type signature, but why do all that work when we can make the compiler do it for us?

How to make a algebraic data type list

Hi I'm currently trying to use the elem function in prelude.
data MyType = A Int
| B Int Int
| C Int
| D Int Int
deriving (Show,Eq)
list = [ A _, B _ _ ]
or
list = [ A Int, B Int Int ]
bool = (A 12) elem list -- use like this to get a Boolean value.
The problem is the list, it will (both) have compile error. Can someone tell me the right way to define list?
Oops about the data and deriving (Show,Eq) in my main code I did do all that. The reason for this question is that I have a big list of MyType and I want to cherry pick one or two of the types out of the big list modify it then put it back, how do I do that?
Exp.
bigList=[ A 3, C 6, A 5, B 5 8, D 5 6 ]
I would like to pick out only the data type ( A Int ) and (B Int Int) , maybe change all value for the two data type into 0, after modification put back so I end up with a new list.
newBigList=[ A 0, C 6, A 0, B 0 0, D 5 6 ]
Thanks
First of all, it is data and not Data.
Second, you are mixing type variables (Int) with values in defining list, while _ can only be used in pattern matching. You should write this instead to build a list of type [MyType]:
list = [A 12, B 1 5]
Third, your declaration for bool uses elem :: Eq a => a -> [a] -> Bool as an infix operator, while it is a function like any other. Write either
bool = elem (A 12) list
or
bool = (A 12) `elem` list
As you see from the type signature of elem, you need to derive the Eq typeclass. It could be useful to be able to print your MyType values also, so you may consider adding deriving (Eq,Show) at the end of your type declaration.
It seems like you're mistaking Haskell for Prolog. Haskell do not work by unification like Prolog. You should start reading a good tutorial or book from the basics.

Resources