[Haskell-cafe] generics-sop equivalent of everywhere/mkT?

Li-yao Xia lysxia at gmail.com
Tue Feb 26 02:23:41 UTC 2019


I don't know about generics-sop examples, but the `types` traversal in 
generic-lens comes close. That could be a source of inspiration if 
you're considering implementing such deep traversals with SOP.

http://hackage.haskell.org/package/generic-lens-1.1.0.0/docs/Data-Generics-Product-Types.html

Li-yao

On 2/25/19 8:36 PM, Scott Michel wrote:
> The corresponding gensop.cabal:
> 
> cabal-version:  >= 1.12
> name:           gensop
> version:        0.1
> build-type:     Simple
> description:    No description.
> license:        GPL-3
> 
> executable gensop
>    default-language:     Haskell2010
>    main-is: Main.hs
>    build-depends:
>      base,
>      containers,
>      bytestring,
>      generics-sop,
>      syb,
>      text,
>      unordered-containers
> 
>    default-extensions:
>      OverloadedStrings,
>      FlexibleInstances
> 
>    ghc-options: -Wall
> 
> 
> On Mon, Feb 25, 2019 at 4:51 PM Scott Michel <scooter.phd at gmail.com> wrote:
> 
>> Here's the cut down code. I'd like to replace the "everywhere (mkT
>> fixupSymbol)" in the main with an equivalent Generics.SOP construction,
>> which effectively recurses into the product to replace/transform the
>> AbsAddr with a SymAddr if the hash table lookup succeeds. While I don't
>> object to SYB, it seems awkward to "mix and match" the two generic
>> libraries.
>>
>>
>> V/R
>> -scooter
>>
>> {-# LANGUAGE DataKinds            #-}
>> {-# LANGUAGE TypeFamilies         #-}
>> {-# LANGUAGE TemplateHaskell      #-}
>> {-# LANGUAGE DeriveDataTypeable #-}
>>
>> module Main where
>>
>> import Data.Data
>> import Data.Foldable (foldl)
>> import Data.Int
>> import Data.Word (Word8, Word16)
>> import Data.Text (Text)
>> import qualified Data.Text as T
>> import qualified Data.Text.IO as T
>> import Text.Printf
>> import Generics.SOP
>> import Generics.SOP.TH (deriveGeneric)
>> import Data.Generics.Aliases (mkT)
>> import Data.Generics.Schemes (everywhere)
>> import Data.HashMap.Strict (HashMap)
>> import qualified Data.HashMap.Strict as H
>> import Data.Sequence (Seq, (><), (|>))
>> import qualified Data.Sequence as Seq
>>
>>
>> type Z80addr = Word16
>> type Z80word = Word8
>>
>> class Z80operand x where
>>    formatOperand :: x -> Text
>>
>> main :: IO()
>> main = mapM_ T.putStrLn (foldl printIns Seq.empty $ everywhere (mkT
>> fixupSymbol) insnSeq)
>> -- -------------------------------------------------^ Does this have a
>> Generics.SOP equivalent?
>>    where
>>      printIns accum ins = accum |> T.concat ([mnemonic, gFormatOperands]
>> <*> [ins])
>>
>>      mnemonic (LD _)   = "LD   "
>>      mnemonic (CALL _) = "CALL "
>>
>>      -- Generics.SOP: Fairly straightforward
>>      gFormatOperands {-elt-} =
>>        T.intercalate ", " . hcollapse . hcmap disOperandProxy (mapIK
>> formatOperand) . from {-elt-}
>>        where
>>          disOperandProxy = Proxy :: Proxy Z80operand
>>
>>      -- Translate an absolute address, generally hidden inside an
>> instruction operand, into a symbolic address
>>      -- if present in the symbol table.
>>      fixupSymbol addr@(AbsAddr absAddr) = maybe addr SymAddr (absAddr
>> `H.lookup` symtab)
>>      fixupSymbol other                  = other
>>
>>      insnSeq :: Seq Z80instruction
>>      insnSeq = Seq.singleton (LD (Reg8Imm B 0x0))
>>                |> (LD (Reg8Indirect C (AbsAddr 0x1234)))
>>                |> (CALL (AbsAddr 0x4567))
>>
>>      symtab :: HashMap Z80addr Text
>>      symtab = H.fromList [ (0x1234, "label1"), (0x4567, "label2")]
>>
>> -- | Symbolic and absolute addresses. Absolute addresses can be translated
>> into symbolic
>> -- labels.
>> data SymAbsAddr  = AbsAddr Z80addr | SymAddr Text
>>    deriving (Eq, Ord, Typeable, Data)
>>
>> data Z80reg8 = A | B | C
>>    deriving (Eq, Ord, Typeable, Data)
>>
>> -- | Cut down version of the Z80 instruction set
>> data Z80instruction = LD OperLD | CALL SymAbsAddr
>>    deriving (Eq, Ord, Typeable, Data)
>>
>> -- | Load operands
>> data OperLD = Reg8Imm Z80reg8 Z80word | Reg8Indirect Z80reg8 SymAbsAddr
>>    deriving (Eq, Ord, Typeable, Data)
>>
>> $(deriveGeneric ''SymAbsAddr)
>> $(deriveGeneric ''Z80reg8)
>> $(deriveGeneric ''Z80instruction)
>> $(deriveGeneric ''OperLD)
>>
>> instance Z80operand Z80word where
>>    formatOperand word = T.pack $ printf "0x%04x" word
>>
>> instance Z80operand SymAbsAddr where
>>    formatOperand (AbsAddr addr)  = T.pack $ printf "0x04x" addr
>>    formatOperand (SymAddr label) = label
>>
>> instance Z80operand Z80reg8 where
>>    formatOperand A = "A"
>>    formatOperand B = "B"
>>    formatOperand C = "C"
>>
>> instance Z80operand OperLD where
>>    formatOperand (Reg8Imm reg imm) = T.concat [formatOperand reg, ", ",
>> formatOperand imm]
>>    formatOperand (Reg8Indirect reg addr) = T.concat [formatOperand reg, ",
>> ", formatOperand addr]
>>
>>
>> On Sun, Feb 24, 2019 at 10:07 PM Scott Michel <scooter.phd at gmail.com>
>> wrote:
>>
>>> Before I cut down my code to a test case, are there any examples of a
>>> generics-sop equivalent of syb's everywhere/mkT? What's the way to operate
>>> on a product, replace the "I" argument with a compatible argument and walk
>>> back through the isomorphism, i.e. "to $ <something> $ from".
>>>
>>> I'm hacking on a Z80 system emulator (TRS-80 Model I system, more
>>> specifically). There are a couple of places where it'd be smoother in the
>>> disassembler to transform the disassembled instruction sequence (converting
>>> addresses to labels) before output. Consequently, cutting down code to an
>>> example is a bit painful -- examples would help.
>>>
>>>
>>> -scooter
>>>
>>
> 
> 
> _______________________________________________
> 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