2011-12-04 7 views
11

というハスケル関数は、FlexableInstancesのないHaskellプログラム、すなわち純粋なHaskell2010を表現できますか?FlexibleInstancesを持たない可変引数関数を引数としてとり、Haskell2010

{-# LANGUAGE FlexibleInstances #-} 

class Funk a  where truth :: a -> [Bool] 
instance Funk [Bool] where truth = \x -> x 
instance Funk Bool where truth = \x -> [x] 

instance Funk b => Funk (Bool -> b) where 
    truth f = concat [truth (f True), truth (f False)] 

これは、How to write a Haskell function that takes a variadic function as an argumentの答えに触発されています。

truthは、引数として受け取る関数(Boolではなく、[Bool]を返します)以外の何かを返すという問題が疑われます。

このスニペットの目的はすなわち

Main> truth (\x y -> x && y) 
[True,False,False,False] 

Main> truth (\x y -> x || y) 
[True,True,True,False] 

終わりには、真理値表は次のように、印刷する、ブール関数のためのすべての可能な構成のすべての評価のリストを与えることであり、試験および視覚化するためのいくつかのボイラープレートコードがこの機能の目的が何であるか、ここ

Main> main 
T T T | T 
T T F | T 
T F T | T 
T F F | F 
F T T | T 
F T F | F 
F F T | T 
F F F | T 

:(これを生成するコードを参照するために、この記事の最後にボイラープレートを参照)

class TruthTable a where 
    truthTable :: Funk f => f -> a 

instance TruthTable [String] where 
    truthTable f = zipWith (++) (hCells (div (length t) 2)) (map showBool $ truth f) 
     where 
      showBool True = "| T" 
      showBool False = "| F" 
      hCells 1 = ["T ", "F "] 
      hCells n = ["T " ++ x | x <- hCells (div n 2)] ++ ["F " ++ x | x <- hCells (div n 2)] 

instance TruthTable [Char] where 
    truthTable f = foldl1 join (truthTable f) 
     where join a b = a ++ "\n" ++ b 

instance TruthTable (IO a) where 
    truthTable f = putStrLn (truthTable f) >> return undefined 

main :: IO() 
main = truthTable (\x y z -> x `xor` y ==> z) 

xor :: Bool -> Bool -> Bool 
xor a b = not $ a == b 

(==>) :: Bool -> Bool -> Bool 
a ==> b = not $ a && not b 

答えて

12

問題ありません:

class Funk a     where truth :: a -> [Bool] 
instance (IsBool a) => Funk [a] where truth = map toBool 
instance Funk Bool    where truth = \x -> [x] 

instance (IsBool a, Funk b) => Funk (a -> b) where 
    truth f = concat [truth (f $ fromBool True), truth (f $ fromBool False)] 

class IsBool a where 
    toBool :: a -> Bool 
    fromBool :: Bool -> a 

instance IsBool Bool where 
    toBool = id 
    fromBool = id 

あなたも、あなたが他の読者に明確にするため、0と1など

+0

ああ、ありがとう。私はText.PrintfのIsCharと同様の "トリック"を見たことがあります。 – scravy

1

Haskell98の方法は、([]ブール値)とするためのnewtypesを使用することである(( - >)ブールのB):

newtype LB = LB [Bool] 
newtype FAB b = FAB (Bool -> b) 

class Funk a  where truth :: a -> [Bool] 
instance Funk LB  where truth = \(LB x) -> x 
instance Funk Bool where truth = \x -> [x] 

instance Funk b => Funk (FAB b) where 
    truth (FAB f) = concat [truth (f True), truth (f False)] 

この部分は、次いで必要な言語拡張なしでコンパイル。しかし、「真実」を扱いやすくするというユースケースを排除します。

+0

と整数のように、希望する場合、FlexibleInstancesはへの安全な拡張機能である「名誉ブール」することができます型システム。 GHCのドキュメントはhttp://www.haskell.org/ghc/docs/latest/html/users_guide/type-class-extensions.html#instance-rules –

+1

にあります。私はこの正確なことを尋ねました:http://stackoverflow.com/questions/8367423/are-haskell-flexibleinstances-a-stable-to-the-languageを使っていましたが、私は拡張機能を持たないソリューションに興味がありました。 – scravy

関連する問題