I'm trying to make a type using the singletons library where I use a list:
import Data.Singletons.TH (singletons)
$(singletons [d|
data LLVMType
= IntegerType
| FloatType
| FunctionType { argumentTypes :: [LLVMType] }
|])
foo :: SLLVMType ('FunctionType '[ 'IntegerType ])
foo = ???
I tried to make foo be: SFunctionType [SIntegerType], however it results in this error:
• Couldn't match expected type ‘Data.Singletons.Sing '['IntegerType]’
with actual type ‘[Data.Singletons.Sing 'IntegerType]’
• In the first argument of ‘SFunctionType’, namely ‘[SIntegerType]’
In the expression: SFunctionType [SIntegerType]
In an equation for ‘foo’: foo = SFunctionType [SIntegerType]
How do I make an expression for foo that typechecks? Or how can I achieve this in another way?
Github repo with the code.
You're very close, but you need to use list singletons.
{-# language TemplateHaskell, DataKinds, GADTs, TypeFamilies #-}
module SingList where
import Data.Singletons.TH (singletons)
import Data.Singletons.Prelude.List (Sing (SNil, SCons))
$(singletons [d|
data LLVMType
= IntegerType
| FloatType
| FunctionType { argumentTypes :: [LLVMType] }
|])
foo :: SLLVMType ('FunctionType '[ 'IntegerType ])
foo = SFunctionType (SCons SIntegerType SNil)
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I've tried to code a typed version of the first homework exercise. It compiles but fails to render in the playground...
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
import Control.Monad hiding (fmap)
import GHC.Generics (Generic)
import Data.Aeson (FromJSON, ToJSON)
import Data.Map as Map
import Data.Text (Text)
import Data.Void (Void)
import Plutus.Contract hiding (when)
import PlutusTx (Data (..))
import qualified PlutusTx
import PlutusTx.Prelude hiding (Semigroup(..), unless)
import Ledger hiding (singleton)
import Ledger.Constraints as Constraints
import qualified Ledger.Scripts as Scripts
import qualified Ledger.Typed.Scripts as Scripts
import Ledger.Ada as Ada
import Playground.Contract (printJson, printSchemas, ensureKnownCurrencies, stage, ToSchema)
import Playground.TH (mkKnownCurrencies, mkSchemaDefinitions)
import Playground.Types (KnownCurrency (..))
import Prelude (Semigroup (..))
import Text.Printf (printf)
newtype DuoBoolRedeemer = DuoBoolRedeemer (Bool, Bool)
deriving (Generic, ToSchema)
PlutusTx.unstableMakeIsData ''DuoBoolRedeemer
{-# INLINABLE mkValidator #-}
-- This should validate if and only if the two Booleans in the redeemer are equal!
mkValidator :: () -> DuoBoolRedeemer -> ValidatorCtx -> Bool
mkValidator _ (DuoBoolRedeemer (b1,b2)) _ = traceIfFalse "wrong redeemer" $ b1 == b2
data Typed
instance Scripts.ScriptType Typed where
type instance DatumType Typed = ()
type instance RedeemerType Typed = DuoBoolRedeemer
inst :: Scripts.ScriptInstance Typed
inst = Scripts.validator #Typed
$$(PlutusTx.compile [|| mkValidator ||])
$$(PlutusTx.compile [|| wrap ||])
where
wrap = Scripts.wrapValidator #() #DuoBoolRedeemer
validator :: Validator
validator = Scripts.validatorScript inst
valHash :: Ledger.ValidatorHash
valHash = Scripts.validatorHash validator
scrAddress :: Ledger.Address
scrAddress = ScriptAddress valHash
type GiftSchema =
BlockchainActions
.\/ Endpoint "give" Integer
.\/ Endpoint "grab" DuoBoolRedeemer
give :: (HasBlockchainActions s, AsContractError e) => Integer -> Contract w s e ()
give amount = do
let tx = mustPayToTheScript () $ Ada.lovelaceValueOf amount
ledgerTx <- submitTxConstraints inst tx
void $ awaitTxConfirmed $ txId ledgerTx
logInfo #String $ printf "made a gift of %d lovelace" amount
grab :: forall w s e. (HasBlockchainActions s, AsContractError e) => DuoBoolRedeemer -> Contract w s e ()
grab bs = do
utxos <- utxoAt scrAddress
let orefs = fst <$> Map.toList utxos
lookups = Constraints.unspentOutputs utxos <>
Constraints.otherScript validator
tx :: TxConstraints Void Void
tx = mconcat [mustSpendScriptOutput oref $ Redeemer $ PlutusTx.toData bs | oref <- orefs]
ledgerTx <- submitTxConstraintsWith #Void lookups tx
void $ awaitTxConfirmed $ txId ledgerTx
logInfo #String $ "collected gifts"
endpoints :: Contract () GiftSchema Text ()
endpoints = (give' `select` grab') >> endpoints
where
give' = endpoint #"give" >>= give
grab' = endpoint #"grab" >>= grab
mkSchemaDefinitions ''GiftSchema
mkKnownCurrencies []
I don't understand why it fails. In the playground, for the "grab" action I have the message "Unsuported non record constructor". I think the problem is with ToSchema which may only accept reccords, but if I don't use it, I have an error message requiring it... I don't understand.
I'm no expert, but can you try a:
.\/ Endpoint "grab" (Bool, Bool)
Given that the simulator, imho, only expects simpler things
I wanted to encode a simple "map" in JSON:
{ "CS": "Ahoj"
, "EN": "Hello"
}
My attempt:
{-# LANGUAGE TemplateHaskell, DeriveGeneric, DeriveAnyClass #-}
import Data.Aeson
import Data.Aeson.TH (deriveJSON)
import Data.Text (Text)
import qualified Data.HashMap.Lazy as M
import GHC.Generics (Generic)
import Data.Hashable (Hashable)
data Language
= CS
| EN
deriving (Eq, Show, Generic, Hashable)
deriveJSON defaultOptions ''Language
newtype TranslatedText =
TranslatedText (M.HashMap Language Text)
deriving (Eq, Show, Generic)
deriveJSON defaultOptions ''TranslatedText
I am getting:
/xxx/src/Data.hs:80:1: error:
• No instance for (FromJSONKey Language)
arising from a use of ‘parseJSON’
• In the second argument of ‘(<$>)’, namely ‘parseJSON arg_apgG’
In the expression: (TranslatedText <$> parseJSON arg_apgG)
In a case alternative:
arg_apgG -> (TranslatedText <$> parseJSON arg_apgG)
|
80 | deriveJSON defaultOptions ''TranslatedText
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/xxx/src/Data.hs:80:1: error:
• No instance for (ToJSONKey Language)
arising from a use of ‘toJSON’
• In the expression: toJSON arg1_apfY
In a case alternative: TranslatedText arg1_apfY -> toJSON arg1_apfY
In the expression:
case value_apdm of { TranslatedText arg1_apfY -> toJSON arg1_apfY }
|
80 | deriveJSON defaultOptions ''TranslatedText
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/xxx/src/Data.hs:80:1: error:
• No instance for (ToJSONKey Language)
arising from a use of ‘toEncoding’
• In the expression: toEncoding arg1_apgk
In a case alternative:
TranslatedText arg1_apgk -> toEncoding arg1_apgk
In the expression:
case value_apg9 of {
TranslatedText arg1_apgk -> toEncoding arg1_apgk }
|
80 | deriveJSON defaultOptions ''TranslatedText
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I tried writing FromJSONKey and ToJSONKey instances using readMaybe and show, but I don't know how one should construct a Parser? Or is there some better, more automatic way? After all the sum type can easily be converted from/to Text.
Here is what a typical instance looks like, using Show and Read (a deriving clause for Read needs to be added to Language):
-- Additional imports
import qualified Data.Text as T
import Text.Read (readMaybe)
instance ToJSONKey Language where
toJSONKey = toJSONKeyText (T.pack . show)
instance FromJSONKey Language where
fromJSONKey = FromJSONKeyTextParser $ \t -> case readMaybe (T.unpack t) of
Just k -> pure k
Nothing -> fail ("Invalid key: " ++ show t)
There should be a shorter way, I've submitted a proposal to add generic implementations: https://github.com/bos/aeson/issues/710
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeOperators #-}
import qualified Data.ByteString.Lazy as BL
import Data.Csv (DefaultOrdered, FromRecord,
ToNamedRecord, ToRecord)
import Data.Generics
import Data.Proxy
import qualified Data.Text as T
import Network.HTTP.Client (newManager)
import Network.HTTP.Client.TLS (tlsManagerSettings)
import Servant.API
import Servant.Client
import Servant.CSV.Cassava
import System.Environment
data Cata = Cata
{
csvDate :: String,
csvOpen :: String,
csvHigh :: String,
csvLow :: String,
csvClose :: String,
csvVolume :: String,
csvExDividend :: String,
csvSplitRatio :: String,
csvAdjOpen :: String,
csvAdjHigh :: String,
csvAdjLow :: String,
csvAdjClose :: String,
csvAdjVolume :: String
} deriving (Show, Generic)
instance DefaultOrdered Cata
instance FromRecord Cata
instance ToNamedRecord Cata
instance ToRecord Cata
I compile the above code and get the following error: why?
$ stack ghc servantcsv.hs
[1 of 1] Compiling Main ( servantcsv.hs, servantcsv.o )
servantcsv.hs:34:21: error:
• Illegal deriving item ‘Generic’
• In the data declaration for ‘Cata’
|
34 | } deriving (Show, Generic)
| ^^^^^^^
GHC Version: ghc-8.4.3
You want to import GHC.Generics not Data.Generics. What you have imported does have a type Generic but it isn't a class:
type Generic c = forall a. Data a => a -> c a
Certainly that can't be part of a "deriving" clause.
I'm trying to follow the tutorial for the Beam Haskell library: https://tathougies.github.io/beam/tutorials/tutorial1/
module Lib
( someFunc
) where
{-# LANGUAGE
DeriveGeneric
, GADTs
, OverloadedStrings
, FlexibleContexts
, FlexibleInstances
, TypeFamilies
, TypeApplications
#-}
import Database.Beam
import Database.Beam.Postgres
import GHC.Generics
import Data.Text (Text)
data UserT f
= User
{ _userEmail :: Columnar f Text
, _userFirstName :: Columnar f Text
, _userLastName :: Columnar f Text
, _userPassword :: Columnar f Text }
deriving Generic
someFunc :: IO ()
someFunc = putStrLn "someFunc"
This results in the following error:
• Can't make a derived instance of ‘Generic (UserT f)’:
You need DeriveGeneric to derive an instance for this class
• In the data declaration for ‘UserT’
|
27 | deriving Generic
| ^^^^^^^
Note that the DeriveGeneric language pragma is present.
What am I missing here?
Build environment:
stack lts-11.9
Linux
A {-# LANGUAGE #-} declaration needs to go at the very top of the file, before the module declaration.
Looking at part of the servant example, I see:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
module Main where
import Prelude ()
import Prelude.Compat
import Control.Monad.Except
import Control.Monad.Reader
import Data.Aeson.Types
import Data.Attoparsec.ByteString
import Data.ByteString (ByteString)
import Data.List
import Data.Maybe
import Data.String.Conversions
import Data.Time.Calendar
import GHC.Generics
import Lucid
import Network.HTTP.Media ((//), (/:))
import Network.Wai
import Network.Wai.Handler.Warp
import Servant
import System.Directory
import Text.Blaze
import Text.Blaze.Html.Renderer.Utf8
import qualified Data.Aeson.Parser
import qualified Text.Blaze.Html
type UserAPI1 = "users" :> Get '[JSON] [User]
data User = User
{ name :: String
, age :: Int
, email :: String
, registration_date :: Day
} deriving (Eq, Show, Generic)
instance ToJSON User
When I removed the deriving of Generic, I got the following error:
• No instance for (Generic User)
arising from a use of ‘aeson-1.1.2.0:Data.Aeson.Types.ToJSON.$dmtoJSON’
So, it appears that the Generic typeclass instance for User enables instance ToJSON User to, I'm assuming, create a JSON Encoder for User.
What's the machinery of instance ToJSON User, i.e. type signature, if that's the right word?
I'm trying to look at its type from the stack ghci, i.e. REPL, but failing:
λ: >:t instance
<interactive>:1:1: error: parse error on input ‘instance’
λ: >:i instance
<interactive>:1:1: error: parse error on input ‘instance’
Let's look at the source for ToJSON:
class ToJSON a where
-- | Convert a Haskell value to a JSON-friendly intermediate type.
toJSON :: a -> Value
default toJSON :: (Generic a, GToJSON Zero (Rep a)) => a -> Value
toJSON = genericToJSON defaultOptions
The ToJSON class has a default toJSON implementation with additional type constraints (including Generic, as you've noticed). This requires the DefaultSignatures extension; notice at the top of that module you can see
{-# LANGUAGE DefaultSignatures #-}
The other constraint, GToJSON Zero (Rep a), imposes some further restrictions on the structure of a, and so not every type with a Generic instance will satisfy this signature.
Regarding your question about GHCi: instance is a Haskell keyword. Inspecting toJSON may be what you want instead. This will show you the same information we saw in the source:
λ> :i toJSON
class ToJSON a where
toJSON :: a -> Value
default toJSON :: (GHC.Generics.Generic a,
GToJSON Zero (GHC.Generics.Rep a)) =>
a -> Value
...
-- Defined in ‘aeson-1.1.2.0:Data.Aeson.Types.ToJSON’