Add element to a list which is part of a type in Haskell - haskell

I am trying to add a new element of type Transaction as defined:
--Build type Transaction--
data Transaction = Transaction {
start_state :: Int,
symbol :: Char,
end_state :: Int
} deriving Show
to the list of transactions which is part of the following type:
--Build type Automaton--
data Automaton = Automaton {
initial_state :: Int,
states :: Set.Set Int,
transactions :: [Transaction],
final_states :: Set.Set Int
} deriving Show
I have tried to implement the following function:
--Add to the automaton a transaction
insert_transaction :: Transaction -> Automaton -> Automaton
insert_transaction t a = a{transactions = t : transactions }
but it returns the following error:
automaton.hs:25:48: error:
• Couldn't match expected type ‘[Transaction]’
with actual type ‘Automaton -> [Transaction]’
• Probable cause: ‘transactions’ is applied to too few arguments
In the second argument of ‘(:)’, namely ‘transactions’
In the ‘transactions’ field of a record
In the expression: a {transactions = t : transactions}
|
25 | insert_transaction t a = a{transactions = t : transactions }
| ^^^^^^^^^^^^
How can I implement this?
Thank you!

transactions is not really a value of type [Transaction], it's by itself† only a record field accessor to a field of type [Transaction]. I.e., it's a function. GHCi could have told you:
Main*> :t transactions
transactions :: Automaton -> Transactions
So, to access those transactions, you need to be explicit what automaton from, by just giving it as an argument:
insertTransaction :: Transaction -> Automaton -> Automaton
insertTransaction t a = a{ transactions = t : transactions a }
†“By itself” meaning: when you use it in a normal Haskell expression without special record syntax like a{transactions = ...}. There, the transactions isn't really an independent entity at all.
There are a couple of alternatives you could consider:
You can “partially pattern match” on the fields of a record you pass as a function argument.
insertTransaction t a{transactions = oldTransactions}
= a{ transactions = t : oldTransactions }
The RecordWildCards extension can bring an entire record's fields in scope as overloaded variables, somewhat like as if you're in an OO method of the class containing those fields. This allows you to write essentially what you had originally:
{-# LANGUAGE RecordWildCards #-}
insertTransaction t a{..} = a{ transactions = t : transactions }
I would not recommend this: RecordWildCards is an unidiomatic hack around the limitations of Haskell98' record types.
Lenses are the modern and consequent way to use records in Haskell. You can get them most easily by slightly changing your data definition:
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
data Automaton = Automaton {
_initialState :: Int
, _states :: Set.Set Int
, _transactions :: [Transaction]
, _finalStates :: Set.Set Int
} deriving (Show)
makeLenses ''Automaton -- Generates `transactions` etc. not as plain accessor
-- functions, but as “optics” which can both get
-- and set field values.
insertTransaction :: Transaction -> Automaton -> Automaton
insertTransaction t = transactions %~ (t:)

Related

Is there a canonical way of comparing/changing one/two records in haskell?

I want to compare two records in haskell, without defining each change in the datatype of the record with and each function of 2 datas for all of the elements of the record over and over.
I read about lens, but I could not find an example for that,
and do not know where begin to read in the documentation.
Example, not working:
data TheState = TheState { number :: Int,
truth :: Bool
}
initState = TheState 77 True
-- not working, example:
stateMaybe = fmap Just initState
-- result should be:
-- ANewStateType{ number = Just 77, truth = Just True}
The same way, I want to compare the 2 states:
state2 = TheState 78 True
-- not working, example
stateMaybe2 = someNewCompare initState state2
-- result should be:
-- ANewStateType{ number = Just 78, truth = Nothing}
As others have mentioned in comments, it's most likely easier to create a different record to hold the Maybe version of the fields and do the manual conversion. However there is a way to get the functor like mapping over your fields in a more automated way.
It's probably more involved than what you would want but it's possible to achieve using a pattern called Higher Kinded Data (HKD) and a library called barbies.
Here is a amazing blog post on the subject: https://chrispenner.ca/posts/hkd-options
And here is my attempt at using HKD on your specific example:
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
-- base
import Data.Functor.Identity
import GHC.Generics (Generic)
-- barbie
import Data.Barbie
type TheState = TheState_ Identity
data TheState_ f = TheState
{ number :: f Int
, truth :: f Bool
} deriving (Generic, FunctorB)
initState :: TheState
initState = TheState (pure 77) (pure True)
stateMaybe :: TheState_ Maybe
stateMaybe = bmap (Just . runIdentity) initState
What is happening here, is that we are wrapping every field of the record in a custom f. We now get to choose what to parameterise TheState with in order to wrap every field. A normal record now has all of its fields wrapped in Identity. But you can have other versions of the record easily available as well. The bmap function let's you map your transformation from one type of TheState_ to another.
Honestly, the blog post will do a much better job at explaining this than I would. I find the subject very interesting, but I am still very new to it myself.
Hope this helped! :-)
How to make a Functor out of a record. For that I have an answer: apply the function to > all of the items of the record.
I want to use the record as an heterogenous container / hashmap, where
the names determine the values-types
While there's no "easy", direct way of doing this, it can be accomplished with several existing libraries.
This answer uses red-black-record library, which is itself built over the anonymous products of sop-core. "sop-core" allows each field in a product to be wrapped in a functor like Maybe and provides functions to manipulate fields uniformly. "red-black-record" inherits this, adding named fields and conversions from normal records.
To make TheState compatible with "red-black-record", we need to do the following:
{-# LANGUAGE DataKinds, FlexibleContexts, ScopedTypeVariables,
DeriveGeneric, DeriveAnyClass,
TypeApplications #-}
import GHC.Generics
import Data.SOP
import Data.SOP.NP (NP,cliftA2_NP) -- anonymous n-ary products
import Data.RBR (Record, -- generalized record type with fields wrapped in functors
I(..), -- an identity functor for "simple" cases
Productlike, -- relates a map of types to its flattened list of types
ToRecord, toRecord, -- convert a normal record to its generalized form
RecordCode, -- returns the map of types correspoding to a normal record
toNP, fromNP, -- convert generalized record to and from n-ary product
getField) -- access field from generalized record using TypeApplication
data TheState = TheState { number :: Int,
truth :: Bool
} deriving (Generic,ToRecord)
We auto-derive the Generic instance that allows other code to introspect the structure of the datatype. This is needed by ToRecord, that allows conversion of normal records into their "generalized forms".
Now consider the following function:
compareRecords :: forall r flat. (ToRecord r,
Productlike '[] (RecordCode r) flat,
All Eq flat)
=> r
-> r
-> Record Maybe (RecordCode r)
compareRecords state1 state2 =
let mapIIM :: forall a. Eq a => I a -> I a -> Maybe a
mapIIM (I val1) (I val2) = if val1 /= val2 then Just val2
else Nothing
resultNP :: NP Maybe flat
resultNP = cliftA2_NP (Proxy #Eq)
mapIIM
(toNP (toRecord state1))
(toNP (toRecord state2))
in fromNP resultNP
It compares two records whatsoever that have ToRecord r instances, and also a corresponding flattened list of types that all have Eq instances (the Productlike '[] (RecordCode r) flat and All Eq flat constraints).
First it converts the initial record arguments to their generalized forms with toRecord. These generalized forms are parameterized with an identity functor I because they come from "pure" values and there aren't any effects are play, yet.
The generalized record forms are in turn converted to n-ary products with toNP.
Then we can use the cliftA2_NP function from "sop-core" to compare accross all fields using their respective Eq instances. The function requires specifying the Eq constraint using a Proxy.
The only thing left to do is reconstructing a generalized record (this one parameterized by Maybe) using fromNP.
An example of use:
main :: IO ()
main = do
let comparison = compareRecords (TheState 0 False) (TheState 0 True)
print (getField #"number" comparison)
print (getField #"truth" comparison)
getField is used to extract values from generalized records. The field name is given as a Symbol by way of -XTypeApplications.

Eta reduce and DuplicateRecordFields language extension

Issue is about having 2 data types, Transaction and FormatModel, both having formatId field. To prevent adding type signatures to get formatId from a transaction or formatModel, I have created type class HasFormat:
class HasFormat a where
formatId_ :: a -> FormatId
instance HasFormat Transaction where
formatId_ x = formatId x -- gives error because ambiguous occurrence ‘formatId’
instance HasFormat FormatModel where
formatId_ = formatId -- this works
Can some explain why the instance which has eta reduced implementation is working and the other one not?
Disambiguation of duplicate record fields is necessarily a best-effort kind of thing because it needs to occur before type checking (you can't generally type check an expression before you know what identifiers the names in it refer to; which is what the disambiguation is doing).
Your non-working example is equivalent to this non-working example from the documentation:
data S = MkS { x :: Int }
data T = MkT { x :: Bool }
bad :: S -> Int
bad s = x s

Safe Record field query

Is there a clean way to avoid the following boilerplate:
Given a Record data type definition....
data Value = A{ name::String } | B{ name::String } | C{}
write a function that safely returns name
getName :: Value -> Maybe String
getName A{ name=x } = Just x
getName B{ name=x } = Just x
getName C{} = Nothing
I know you can do this with Template Haskell, I am looking for a cleaner soln than that, perhaps a GHC extension or something else I've overlooked.
lens's Template Haskell helpers do the right thing when they encounter partial record fields.
{-# LANGUAGE TemplateHaskell #-}
import Control.Applicative
import Control.Lens
data T = A { _name :: String }
| B { _name :: String }
| C
makeLenses ''T
This'll generate a Traversal' called name that selects the String inside the A and B constructors and does nothing in the C case.
ghci> :i name
name :: Traversal' T String -- Defined at test.hs:11:1
So we can use the ^? operator (which is a flipped synonym for preview) from Control.Lens.Fold to pull out Maybe the name.
getName :: T -> Maybe String
getName = (^? name)
You can also make Prism's for the constructors of your datatype, and choose the first one of those which matches using <|>. This version is useful when the fields of your constructors have different names, but you do have to remember to update your extractor function when you add constructors.
makePrisms ''T
getName' :: T -> Maybe String
getName' t = t^?_A <|> t^?_B
lens is pretty useful!
Why don't you use a GADT? I do not know if you are interested in using only records. But, I fell that GADTs provide a clean solution to your problem, since you can restrict what constructors are valid by refining types.
{-# LANGUAGE GADTs #-}
module Teste where
data Value a where
A :: String -> Value String
B :: String -> Value String
C :: Value ()
name :: Value String -> String
name (A s) = s
name (B s) = s
Notice that both A and B produce Value String values while C produces Value (). When you define function
name :: Value String -> String
it specifically says that you can only pass a value that has a string in it. So, you can only pattern match on A or B values. This is useful to avoid the need of Maybe in code.

How can I read the metadata of a type at runtime?

I'd like to write a program that prints out some metadata of a Haskell type. Although I know this isn't valid code, the idea is something like:
data Person = Person { name :: String, age :: Int }
metadata :: Type -> String
metadata t = ???
metadata Person -- returns "Person (name,age)"
The important restriction being I don't have an instance of Person, just the type.
I've started looking into Generics & Typeable/Data, but without an instance I'm not sure they'll do what I need. Can anyone point me in the right direction?
Reflection in Haskell works using the Typeable class, which is defined in Data.Typeable and includes the typeOf* method to get a run-time representation of a value's type.
ghci> :m +Data.Typeable
ghci> :t typeOf 'a'
typeOf 'a' :: TypeRep
ghci> typeOf 'a' -- We could use any value of type Char and get the same result
Char -- the `Show` instance of `TypeRep` just returns the name of the type
If you want Typeable to work for your own types, you can have the compiler generate an instance for you with the DeriveDataTypeable extension.
{-# LANGUAGE DeriveDataTypeable #-}
import Data.Typeable
data Person = Person { name :: String, age :: Int } deriving Typeable
You can also write your own instance, but really, no one has the time for that. Apparently you can't - see the comments
You can now use typeOf to grab a run-time representation of your type. We can query information about the type constructor (abbreviated to TyCon) and its type arguments:
-- (undefined :: Person) stands for "some value of type Person".
-- If you have a real Person you can use that too.
-- typeOf does not use the value, only the type
-- (which is known at compile-time; typeOf is dispatched using the normal instance selection rules)
ghci> typeOf (undefined :: Person)
Person
ghci> tyConName $ typeRepTyCon $ typeOf (undefined :: Person)
"Person"
ghci> tyConModule $ typeRepTyCon $ typeOf (undefined :: Person)
"Main"
Data.Typeable also provides a type-safe cast operation which allows you to branch on a value's runtime type, somewhat like C#'s as operator.
f :: Typeable a => a -> String
f x = case (cast x :: Maybe Int) of
Just i -> "I can treat i as an int in this branch " ++ show (i * i)
Nothing -> case (cast x :: Maybe Bool) of
Just b -> "I can treat b as a bool in this branch " ++ if b then "yes" else "no"
Nothing -> "x was of some type other than Int or Bool"
ghci> f True
"I can treat b as a bool in this branch yes"
ghci> f (3 :: Int)
"I can treat i as an int in this branch 9"
Incidentally, a nicer way to write f is to use a GADT enumerating the set of types you expect your function to be called with. This allows us to lose the Maybe (f can never fail!), does a better job of documenting our assumptions, and gives compile-time feedback when we need to change the set of admissible argument types for f. (You can write a class to make Admissible implicit if you like.)
data Admissible a where
AdInt :: Admissible Int
AdBool :: Admissible Bool
f :: Admissible a -> a -> String
f AdInt i = "I can treat i as an int in this branch " ++ show (i * i)
f AdBool b = "I can treat b as a bool in this branch " ++ if b then "yes" else "no"
In reality I probably wouldn't do either of these - I'd just stick f in a class and define instances for Int and Bool.
If you want run-time information about the right-hand side of a type definition, you need to use the entertainingly-named Data.Data, which defines a subclass of Typeable called Data.** GHC can derive Data for you too, with the same extension:
{-# LANGUAGE DeriveDataTypeable #-}
import Data.Typeable
import Data.Data
data Person = Person { name :: String, age :: Int } deriving (Typeable, Data)
Now we can grab a run-time representation of the values of a type, not just the type itself:
ghci> dataTypeOf (undefined :: Person)
DataType {tycon = "Main.Person", datarep = AlgRep [Person]}
ghci> dataTypeConstrs $ dataTypeOf (undefined :: Person)
[Person] -- Person only defines one constructor, called Person
ghci> constrFields $ head $ dataTypeConstrs $ dataTypeOf (undefined :: Person)
["name","age"]
Data.Data is the API for generic programming; if you ever hear people talking about "Scrap Your Boilerplate", this (along with Data.Generics, which builds on Data.Data) is what they mean. For example, you can write a function which converts record types to JSON using reflection on the type's fields.
toJSON :: Data a => a -> String
-- Implementation omitted because it is boring.
-- But you only have to write the boring code once,
-- and it'll be able to serialise any instance of `Data`.
-- It's a good exercise to try to write this function yourself!
* In recent versions of GHC, this API has changed somewhat. Consult the docs.
** Yes, the fully-qualified name of that class is Data.Data.Data.

Is there a type 'Any' in haskell?

Say, I want to define a record Attribute like this:
data Attribute = Attribute {name :: String, value :: Any}
This is not valid haskell code of course. But is there a type 'Any' which basically say any type will do? Or is to use type variable the only way?
data Attribute a = Attribute {name :: String, value :: a}
Generally speaking, Any types aren't very useful. Consider: If you make a polymorphic list that can hold anything, what can you do with the types in the list? The answer, of course, is nothing - you have no guarantee that there is any operation common to these elements.
What one will typically do is either:
Use GADTs to make a list that can contain elements of a specific typeclass, as in:
data FooWrap where
FooWrap :: Foo a => a -> FooWrap
type FooList = [FooWrap]
With this approach, you don't know the concrete type of the elements, but you know they can be manipulated using elements of the Foo typeclass.
Create a type to switch between specific concrete types contained in the list:
data FooElem = ElemFoo Foo | ElemBar Bar
type FooList = [FooElem]
This can be combined with approach 1 to create a list that can hold elements that are of one of a fixed set of typeclasses.
In some cases, it can be helpful to build a list of manipulation functions:
type FooList = [Int -> IO ()]
This is useful for things like event notification systems. At the time of adding an element to the list, you bind it up in a function that performs whatever manipulation you'll later want to do.
Use Data.Dynamic (not recommended!) as a cheat. However, this provides no guarantee that a specific element can be manipulated at all, and so the above approaches should be preferred.
Adding to bdonlan's answer: Instead of GADTs, you can also use existential types:
{-# LANGUAGE ExistentialQuantification #-}
class Foo a where
foo :: a -> a
data AnyFoo = forall a. Foo a => AnyFoo a
instance Foo AnyFoo where
foo (AnyFoo a) = AnyFoo $ foo a
mapFoo :: [AnyFoo] -> [AnyFoo]
mapFoo = map foo
This is basically equivalent to bdonlan's GADT solution, but doesn't impose the choice of data structure on you - you can use a Map instead of a list, for example:
import qualified Data.Map as M
mFoo :: M.Map String AnyFoo
mFoo = M.fromList [("a", AnyFoo SomeFoo), ("b", AnyFoo SomeBar)]
The data AnyFoo = forall a. Foo a => AnyFoo a bit can also be written in GADT notation as:
data AnyFoo where
AnyFoo :: Foo a => a -> AnyFoo
There is the type Dynamic from Data.Dynamic which can hold anything (well, anything Typeable). But that is rarely the right way to do it. What is the problem that you are trying to solve?
This sounds like a pretty basic question, so I'm going to give an even more basic answer than anybody else. Here's what is almost always the right solution:
data Attribute a = Attribute { name :: String, value :: a }
Then, if you want an attribute that wraps an Int, that attribute would have type Attribute Int, or an attribute that wraps a Bool would have type Attribute Bool, etc. You can create these attributes with values of any type; for example, we can write
testAttr = Attribute { name = "this is only a test", value = Node 3 [] }
to create a value of type Attribute (Tree Int).
If your data needs to be eventually a specific type, You could use Convertible with GADTs. Because as consumer, you are only interested in a the datatype you need to consume.
{-# LANGUAGE GADTs #-}
import Data.Convertible
data Conv b where
Conv :: a -> (a -> b) -> Conv b
Chain :: Conv b -> (b -> c) -> Conv c
unconv :: (Conv b) -> b
unconv (Conv a f) = f a
unconv (Chain c f) = f $ unconv c
conv :: Convertible a b => a -> Conv b
conv a = (Conv a convert)
totype :: Convertible b c => Conv b -> Conv c
totype a = Chain a convert
It is not very difficult to derive functor, comonad and monad instances for this. I can post them if you are interested.
Daniel Wagner response is the right one: almost in 90% of cases using a polymorphic type is all that you need.
All the other responses are useful for the remaining 10% of cases, but if you have still no good knowledge of polymorphism as to ask this question, it will be extremely complicated to understand GADTs or Existential Types...
My advice is "keep it as simple as possible".

Resources