7

I've written a small program to find the prime factorization of a number. Everything seems to compile except for the main function, which complains about not being able to find a Show1 instance.

{-# LANGUAGE DeriveFunctor #-}

module FactorAnamorphism where

import Data.Functor.Foldable
import Data.List

nextPrimeFactor :: Integer -> Maybe Integer
nextPrimeFactor n = find (\x -> n `mod` x /= 0) [2..(floor $ sqrt $ fromIntegral n)]

data ExprF r = FactorF Integer | MultF r r deriving (Show, Functor)
type Expr = Fix ExprF

factor :: Integer -> Expr
factor = ana coAlg where
  coAlg fac = case (nextPrimeFactor fac) of
    Just prime -> MultF prime (fac `div` prime)
    Nothing    -> FactorF fac

main :: IO ()
main = putStrLn $ show $ factor 10

Logs:

 % stack build
haskell-playground-0.1.0.0: build (lib + exe)
Preprocessing library haskell-playground-0.1.0.0...
Preprocessing executable 'factor-anamorphism' for
haskell-playground-0.1.0.0...
[1 of 1] Compiling FactorAnamorphism ( app/FactorAnamorphism.hs, .stack-work/dist/x86_64-osx/Cabal-1.24.2.0/build/factor-anamorphism/factor-anamorphism-tmp/FactorAnamorphism.o )

/Users/ian/proj/macalinao/haskell-playground/app/FactorAnamorphism.hs:22:19: error:
    • No instance for (Data.Functor.Classes.Show1 ExprF)
        arising from a use of ‘show’
    • In the second argument of ‘($)’, namely ‘show $ factor 10’
      In the expression: putStrLn $ show $ factor 10
      In an equation for ‘main’: main = putStrLn $ show $ factor 10

--  While building package haskell-playground-0.1.0.0 using:
      /Users/ian/.stack/setup-exe-cache/x86_64-osx/Cabal-simple_mPHDZzAJ_1.24.2.0_ghc-8.0.2 --builddir=.stack-work/dist/x86_64-osx/Cabal-1.24.2.0 build lib:haskell-playground exe:factor-anamorphism exe:haskell-playground-exe --ghc-options " -ddump-hi -ddump-to-file"
    Process exited with code: ExitFailure 1
Ian Macalinao
  • 1,608
  • 3
  • 20
  • 30

1 Answers1

13

The instance of Show for Fix is: Show1 f => Show (Fix f), which is why the compiler expects Show1 ExprF.

Show1 can be found in base under Data.Functor.Classes, and there is a TH script to derive it in Text.Show.Deriving from deriving-compat.

Li-yao Xia
  • 31,896
  • 2
  • 33
  • 56
  • Thanks. Excuse my ignorance, but how would I invoke a template Haskell script? Also, it looks like deriving-compat is a compat library-- would I need to use this if I'm on the latest version of GHCi? – Ian Macalinao Apr 23 '17 at 05:42
  • 3
    Add `{-# LANGUAGE TemplateHaskell #-}` at the top of your file, import `Text.Show.Deriving`, add `$(deriveShow1 ''ExprF)` next to your data declaration. `deriving-compat` is more than a simple compat library, as the functionality provided by `deriveShow1` for instance can not be found anywhere else at the moment, even on the latest GHC. – Li-yao Xia Apr 23 '17 at 11:41
  • Just a question, where did `Show1` come from? I can't find any documentation about this aspect of Haskell. – CMCDragonkai May 26 '18 at 09:47
  • Sorry, I don't know a good reference about this. `Show1` and similar classes as they appear in `base` originally came from `transformers` a major user of higher-kinded types, which motivated those classes. – Li-yao Xia May 26 '18 at 13:28