[Haskell-cafe] Need help to get started with GHC.Generics
Li-yao Xia
lysxia at gmail.com
Thu Sep 10 16:35:38 UTC 2020
This doesn't sound like a use case for generics then. Just to spare you
the trouble of following a red herring.
On 9/10/2020 12:26 PM, YueCompl wrote:
> Li-yao, thanks for the pointer. And my case is not really about ADTs,
> but to introspect the arguments an arbitrary Haskell function takes,
> including how many and what type each argument is, so as to extract
> proper values from a given ArgsPack, then call that Haskell function
> with those values as args it expects.
>
> I'm not sure at a glance, that generics-eot has demonstrated how to
> obtain argument list with type info for a function, and will look into
> the details as I can.
>
> Thanks with regards,
> Compl
>
>
>> On 2020-09-10, at 23:08, Li-yao Xia <lysxia at gmail.com
>> <mailto:lysxia at gmail.com>> wrote:
>>
>> Hi Compl,
>>
>> I couldn't tell what's generic (in the sense of GHC.Generics) about
>> this example. A clearer example would be to give two applications with
>> different algebraic data types, and to show how they consist of the
>> same boilerplate, where the differences are only due to the differing
>> numbers of fields and constructors.
>>
>> As for tutorials on generics, a good starting point might be
>> generics-eot. Its documentation comes with a series of tutorials:
>>
>> https://generics-eot.readthedocs.io/en/stable/
>>
>> Li-yao
>>
>> On 9/10/2020 9:44 AM, YueCompl via Haskell-Cafe wrote:
>>> Dear Cafe,
>>> I'm tinkering with the idea for arbitrary Haskell functions to be
>>> easily called from scripting code, I see auto derive
>>> with GHC.Generics might be the most promising tool, but I'm lost
>>> after read https://wiki.haskell.org/GHC.Generics and hackage docs. I
>>> have no clue so far with how to start with it.
>>> Specifically I want the section highlighted in blue get auto
>>> generated, within the following `runghc` ready example:
>>> ```
>>> {-# LANGUAGEBangPatterns#-}
>>> moduleMain where
>>> importPrelude
>>> importGHC.Generics
>>> importData.Dynamic
>>> -- * minimum data structures as interface with scripting code
>>> typeAttrKey=String
>>> dataAttrVal=NilValue
>>> |IntValue!Integer
>>> |StrValue!String
>>> deriving(Eq,Ord,Typeable)
>>> instanceShowAttrValwhere
>>> show NilValue="nil"
>>> show (IntValue!x)=show x
>>> show (StrValue!x)=show x
>>> dataArgsPack=ArgsPack{
>>> positional'args::[AttrVal]
>>> ,keyword'args::[(AttrKey,AttrVal)]
>>> }
>>> instanceSemigroupArgsPackwhere
>>> (ArgsPackp1 kw1)<>(ArgsPackp2 kw2)=ArgsPack(p1 ++p2)(kw1 ++kw2)
>>> instanceMonoidArgsPackwhere
>>> mempty =ArgsPack[][]
>>> classCallableawhere
>>> call::a->ArgsPack->(AttrVal->IO())->IO()
>>> -- * functions to be callable from scripting code
>>> newtypeAssert=Assert(
>>> Expect->MaybeTarget->Message->IOMessage
>>> )
>>> typeExpect=AttrVal
>>> typeTarget=AttrVal
>>> typeMessage=String
>>> instanceCallableAssertwhere
>>> -- can this get auto-generated ? with
>>> https://wiki.haskell.org/GHC.Generics
>>> call (Assert!assert)(ArgsPack!args !kwargs)!exit =do
>>> (expect,target,message)<-parseApk
>>> result <-assert expect target message
>>> exit $StrValueresult
>>> where
>>> parseApk::IO(Expect,MaybeTarget,Message)
>>> parseApk =goParse
>>> (Left"missing arg: expect",Nothing,Left"missing arg: message")
>>> args
>>> kwargs
>>> goParse (got'expect,got'target,got'message)[][]=casegot'expect of
>>> Leftmsg ->error msg
>>> Rightexpect ->casegot'message of
>>> Leftmsg ->error msg
>>> Rightmessage ->return (expect,got'target,message)
>>> goParse (got'expect,got'target,got'message)args' ((name,val):kwargs')
>>> =casename of
>>> "expect"->casegot'expect of
>>> Right{}->error "duplicate arg: expect"
>>> Left{}->goParse (Rightval,got'target,got'message)args' kwargs'
>>> "target"->casegot'target of
>>> Just{}->error "duplicate arg: target"
>>> Nothing->goParse (got'expect,Justval,got'message)args' kwargs'
>>> "message"->casegot'message of
>>> Right{}->error "duplicate arg: message"
>>> Left{}->caseval of
>>> StrValuemessage ->
>>> goParse (got'expect,got'target,Rightmessage)args' kwargs'
>>> _ ->error "bad arg type for: message"
>>> _ ->error "unexpected keyword args"
>>> goParse (got'expect,got'target,got'message)(val :args')[]=
>>> casegot'expect of
>>> Left{}->goParse (Rightval,got'target,got'message)args' []
>>> Right{}->casegot'target of
>>> Nothing->goParse (got'expect,Justval,got'message)args' []
>>> Just{}->casegot'message of
>>> Left{}->caseval of
>>> StrValuemessage ->
>>> goParse (got'expect,got'target,Rightmessage)args' []
>>> _ ->error "bad arg type for: message"
>>> Right{}->error "extranous positional args"
>>> -- mockup & test out
>>> main::IO()
>>> main =
>>> call
>>> (Assertassert)
>>> (ArgsPack[IntValue333,StrValue"as good will"]
>>> [("target",IntValue333)]
>>> )
>>> $\result ->putStrLn $"Got result: "<>show result
>>> -- | plain Haskell function meant to be easily called by scripting code
>>> assert::Expect->MaybeTarget->Message->IOMessage
>>> assert !expect !maybeTarget !message =casemaybeTarget of
>>> Nothing->return $"* assertion not applicable: "<>message
>>> Justtarget ->ifexpect ==target
>>> thenreturn $"* assertion passed: "<>message
>>> elseerror $"* assertion failed: "<>message
>>> ```
>>> I tried to understand how
>>> * The compiler can provide a default generic implementation for
>>> |parseJSON
>>> <https://hackage.haskell.org/package/aeson-1.5.4.0/docs/Data-Aeson.html#v:parseJSON>|.
>>> is implemented in [aeson](https://hackage.haskell.org/package/aeson)
>>> and it is overwhelming to me at the moment ...
>>> Is there easier scaffold template for me to start with GHC.Generics?
>>> Or there're even better techniques to achieve my final goal?
>>> Help please!
>>> Best regards,
>>> Compl
>>> _______________________________________________
>>> Haskell-Cafe mailing list
>>> To (un)subscribe, modify options or view archives go to:
>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>>> Only members subscribed via the mailman list are allowed to post.
>
More information about the Haskell-Cafe
mailing list