Encode Custom Data Type to Lazy Byte String - haskell

when you want to convert a custom type into bytestring you would do following:
data Foo = Foo {value1 :: Int}
instance Binary Foo where
get =liftM Foo get
put b = put (value1 b)
and if you have a type with multiple viable values as such:
data Foo2 = Foo2A Int | Foo2B Int
instance Binary Foo2 where
get = do flag <- getWord8
case flag of
0 -> fmap Foo2A get
1 -> fmap Foo2B get
put (Foo2A i) = do put (0 :: Word8)
put i
put (Foo2B i) = do put (1 :: Word8)
put i
but if you have a type as such (following...) how would I do this?:
data Foo3 = Foo3A Int | Foo3B
instance Binary Foo3 where
get = do flag <- getWord8
case flag of
0 -> fmap Foo3A get
1 -> ....????? Foo3B has no value - only Data Constructor
put (Foo3A i) = do put (0 :: Word8)
put i
put (Foo3B) = put (1 :: Word8)

You can also derive these instances:
newtype Foo = Foo {value1 :: Int}
deriving newtype Binary
data Foo2 = Foo2A Int | Foo2B Int
deriving stock Generic
deriving anyclass Binary
data Foo3 = Foo3A Int | Foo3B
deriving stock Generic
deriving anyclass Binary

To match what you wrote for put, you want pure Foo3B there in get.

Related

Deriving Eq and Show for an ADT that contains fields that can't have Eq or Show

I'd like to be able to derive Eq and Show for an ADT that contains multiple fields. One of them is a function field. When doing Show, I'd like it to display something bogus, like e.g. "<function>"; when doing Eq, I'd like it to ignore that field. How can I best do this without hand-writing a full instance for Show and Eq?
I don't want to wrap the function field inside a newtype and write my own Eq and Show for that - it would be too bothersome to use like that.
One way you can get proper Eq and Show instances is to, instead of hard-coding that function field, make it a type parameter and provide a function that just “erases” that field. I.e., if you have
data Foo = Foo
{ fooI :: Int
, fooF :: Int -> Int }
you change it to
data Foo' f = Foo
{ _fooI :: Int
, _fooF :: f }
deriving (Eq, Show)
type Foo = Foo' (Int -> Int)
eraseFn :: Foo -> Foo' ()
eraseFn foo = foo{ fooF = () }
Then, Foo will still not be Eq- or Showable (which after all it shouldn't be), but to make a Foo value showable you can just wrap it in eraseFn.
Typically what I do in this circumstance is exactly what you say you don’t want to do, namely, wrap the function in a newtype and provide a Show for that:
data T1
{ f :: X -> Y
, xs :: [String]
, ys :: [Bool]
}
data T2
{ f :: OpaqueFunction X Y
, xs :: [String]
, ys :: [Bool]
}
deriving (Show)
newtype OpaqueFunction a b = OpaqueFunction (a -> b)
instance Show (OpaqueFunction a b) where
show = const "<function>"
If you don’t want to do that, you can instead make the function a type parameter, and substitute it out when Showing the type:
data T3' a
{ f :: a
, xs :: [String]
, ys :: [Bool]
}
deriving (Functor, Show)
newtype T3 = T3 (T3' (X -> Y))
data Opaque = Opaque
instance Show Opaque where
show = const "..."
instance Show T3 where
show (T3 t) = show (Opaque <$ t)
Or I’ll refactor my data type to derive Show only for the parts I want to be Showable by default, and override the other parts:
data T4 = T4
{ f :: X -> Y
, xys :: T4' -- Move the other fields into another type.
}
instance Show T4 where
show (T4 f xys) = "T4 <function> " <> show xys
data T4' = T4'
{ xs :: [String]
, ys :: [Bool]
}
deriving (Show) -- Derive ‘Show’ for the showable fields.
Or if my type is small, I’ll use a newtype instead of data, and derive Show via something like OpaqueFunction:
{-# LANGUAGE DerivingVia #-}
newtype T5 = T5 (X -> Y, [String], [Bool])
deriving (Show) via (OpaqueFunction X Y, [String], [Bool])
You can use the iso-deriving package to do this for data types using lenses if you care about keeping the field names / record accessors.
As for Eq (or Ord), it’s not a good idea to have an instance that equates values that can be observably distinguished in some way, since some code will treat them as identical and other code will not, and now you’re forced to care about stability: in some circumstance where I have a == b, should I pick a or b? This is why substitutability is a law for Eq: forall x y f. (x == y) ==> (f x == f y) if f is a “public” function that upholds the invariants of the type of x and y (although floating-point also violates this). A better choice is something like T4 above, having equality only for the parts of a type that can satisfy the laws, or explicitly using comparison modulo some function at use sites, e.g., comparing someField.
The module Text.Show.Functions in base provides a show instance for functions that displays <function>. To use it, just:
import Text.Show.Functions
It just defines an instance something like:
instance Show (a -> b) where
show _ = "<function>"
Similarly, you can define your own Eq instance:
import Text.Show.Functions
instance Eq (a -> b) where
-- all functions are equal...
-- ...though some are more equal than others
_ == _ = True
data Foo = Foo Int Double (Int -> Int) deriving (Show, Eq)
main = do
print $ Foo 1 2.0 (+1)
print $ Foo 1 2.0 (+1) == Foo 1 2.0 (+2) -- is True
This will be an orphan instance, so you'll get a warning with -Wall.
Obviously, these instances will apply to all functions. You can write instances for a more specialized function type (e.g., only for Int -> String, if that's the type of the function field in your data type), but there is no way to simultaneously (1) use the built-in Eq and Show deriving mechanisms to derive instances for your datatype, (2) not introduce a newtype wrapper for the function field (or some other type polymorphism as mentioned in the other answers), and (3) only have the function instances apply to the function field of your data type and not other function values of the same type.
If you really want to limit applicability of the custom function instances without a newtype wrapper, you'd probably need to build your own generics-based solution, which wouldn't make much sense unless you wanted to do this for a lot of data types. If you go this route, then the Generics.Deriving.Show and Generics.Deriving.Eq modules in generic-deriving provide templates for these instances which could be modified to treat functions specially, allowing you to derive per-datatype instances using some stub instances something like:
instance Show Foo where showsPrec = myGenericShowsPrec
instance Eq Foo where (==) = myGenericEquality
I proposed an idea for adding annotations to fields via fields, that allows operating on behaviour of individual fields.
data A = A
{ a :: Int
, b :: Int
, c :: Int -> Int via Ignore (Int->Int)
}
deriving
stock GHC.Generic
deriving (Eq, Show)
via Generically A -- assuming Eq (Generically A)
-- Show (Generically A)
But this is already possible with the "microsurgery" library, but you might have to write some boilerplate to get it going. Another solution is to write separate behaviour in "sums-of-products style"
data A = A Int Int (Int->Int)
deriving
stock GHC.Generic
deriving
anyclass SOP.Generic
deriving (Eq, Show)
via A <-𝈖-> '[ '[ Int, Int, Ignore (Int->Int) ] ]

newtype-like operational semantics for a GADT where the type fully determines the constructor

Suppose I have a GADT like the following:
data Tag = A | B | C
data Payload (tag :: Tag) where
PA :: Int -> Payload A
PB :: Double -> Payload B
PC :: Bool -> Payload C
I want Payload to have no runtime representation on its own -- i.e. I want to have Coercible Int (Payload A), I want zero-cost pattern matching, and in general I want it to behave as if I had the following three newtype definitions instead:
newtype PayloadA = PA Int
newtype PayloadB = PB Double
newtype PayloadC = PC Bool
Is there a way to convince GHC to give me that?
This looks impossible to achieve, at least with current GHC. Assume your Payload A had the same representation of Int, and so on.
data Tag = A | B | C
data Payload (tag :: Tag) where
PA :: Int -> Payload A
PB :: Double -> Payload B
PC :: Bool -> Payload C
Then, how should we implement this?
foo :: Payload tag -> Int
foo (PA i) = i
foo (PB _) = 1
foo (PC _) = 2
To implement foo, we somehow need to extract the tag from the Payload tag, but that is impossible if Payload tag does not store the tag in its representation.
What we could do, instead, is to separate the runtime tag representation from its payload data.
type family Payload (tag :: Tag) where
Payload 'A = Int
Payload 'B = Double
Payload 'C = Bool
Now, Payload 'A is exactly an Int. We however lose the ability to write foo, since the tag is no longer stored at runtime along the payload. We can instead write this:
-- singleton, could be auto-generated using the singletons library
data STag (tag :: Tag) where
SA :: STag 'A
SB :: STag 'B
SC :: STag 'C
bar :: STag tag -> Payload tag -> Int
bar PA i = i
bar PB _ = 1
bar PC _ = 2
Note how we essentially add the tag as an argument, since we do need it to be represented at runtime.
You can do like:
data family Payload (tag :: Tag)
newtype instance Payload A = PA Int
newtype instance Payload B = PB Double
newtype instance Payload C = PC Bool
This meets your requirement of actually having types distinct from Int, Double, Bool, and of having the operation semantics of a newtype. Of course, the price you pay is you won't be able to pattern-match to determine which is which. But you can recover such things with a typeclass or by explicitly passing the tag (which mostly amount to the same thing under the hood); for example:
class Foo (t :: Tag) where foo :: Payload t -> Int
instance Foo A where foo (PA i) = i
instance Foo B where foo (PB _) = 2
instance Foo C where foo (PC _) = 3

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

Can I match a data constructor wildcard in Haskell?

I have
data Foo = X (String, Int) | A String | B String | C String | D String -- ...
and have defined
f (X (s, _)) =s
f (A s) = s
f (B s) = s
f (C s) = s
f (D s) = s
-- ...
but would prefer to be able to write something like
f (X (s, _)) =s
f (_ s) = s
But there seems to be no way to do this (I get a "parse error" associated with the _).
Is there a way to match a data constructor wildcard in Haskell?
Nope. But you can write this:
data Foo
= X { name :: String, age :: Int }
| A { name :: String }
| B { name :: String }
| C { name :: String }
| D { name :: String }
and then have name :: Foo -> String. You could also consider this:
data Tag = A | B | C | D | X Int
data Foo = Tagged Tag String
f (Tagged _ s) = s
In addition to #DanielWagner's answer, an alternative is to use Scrap your boilerplate (AKA "SYB"). It allows you to find the first subterm of a given type. So you could define
{-# LANGUAGE DeriveDataTypeable #-}
import Control.Monad
import Data.Data
import Data.Generics.Schemes
import Data.Typeable
data Foo = X (String, Int) | A String | B String | C String | D String
deriving (Show, Eq, Ord, Data, Typeable)
fooString :: Foo -> Maybe String
fooString = msum . gmapQ cast
and fooString will return the first String argument of your constructors. Function cast filters out Strings and gmapQ gets the filtered values for all immediate subterms.
However, this won't return the String from X, because X has no immediate String subterm, it has only one subterm of type (String, Int). In order to get the first String anywhere in the term hierarchy, you could use everywhere:
fooString' :: Foo -> Maybe String
fooString' = everything mplus cast
Note that this approach is slightly fragile: It includes simply all Strings it finds, which might not be always what you want, in particular, if you later extend your data type (or some data type that it references).

How to ignore a polymorph readable type, while reading?

I have a problem similar to:
data Foo a = Foo { myInt :: Integer, myValue :: a } deriving Read
bar :: String -> Integer
bar = myInt . read
main = print $ bar stringWithFooOfa
i don't want to use something like read . (!!1) . words, if i don't need to.
Add a type annotation to read. As commenters suggested, Haskell has no way of knowing what you're trying to read since you immediately turn it into an Int. To be more clear, consider this example:
data Foo a = Foo { myInt :: Integer, myValue :: a } deriving Read
data Foo2 a = Foo { myInt2 :: Integer } deriving Read
bar :: String -> Integer
bar = myInt . read
Now there are two very different behaviors for bar possible and it's hard to know which is correct.
To tell Haskell which one you want, use an inline annotation around read:
bar :: String -> Integer
bar = myInt . (read :: String -> Foo ())
Notice that I pick an a, too. Otherwise, we'll be in the same boat as above but just with a instead of Foo.

Resources