Haskell 函数采用可变参数函数作为参数(并返回除该函数之外的其他内容),无需灵活实例,纯 Haskell2010

发布于 2024-12-19 05:44:52 字数 1929 浏览 2 评论 0原文

是否可以在没有FlexibleInstances的情况下(即在纯Haskell2010中)表达以下Haskell程序?

{-# 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)]

这是受到 如何编写一个将可变参数函数作为参数的 Haskell 函数

我怀疑问题是, 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

is it possible to express the following Haskell program without FlexibleInstances, i.e. in pure 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)]

This is inspired by the answer on How to write a Haskell function that takes a variadic function as an argument.

I suspect the problem is, that truth returns something else than the function which it takes as an argument (which returns Bool, not [Bool]).

The purpose of this snippet is, to give a list of all evaluations of all possible configuration for a boolean function, i.e.

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

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

In the end, a truth-table is to be printed, like this (see boiler-plate at the end of this post to see the code which produces this):

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

Here is some boiler-plate code for testing and visualizing, what the purpose of this function is:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你与昨日 2024-12-26 05:44:52

没问题:

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 的整数等。

No problem:

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

You can even make 'honorary booleans' if you wish, like Integer with 0 and 1 etc.

抚你发端 2024-12-26 05:44:52

Haskell98 的方法是对 ([] Bool) 和 ((->) Bool 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)]

然后,这部分无需任何 LANGUAGE 扩展即可编译。但它消除了使“真相”易于使用的用例。

The Haskell98 way is to use newtypes for ([] Bool) and ((->) Bool 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)]

This part then compiles without needed any LANGUAGE extensions. But it eliminates the use case of making 'truth' simple to work with.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文