Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 有可能在哈斯克尔中推广方程吗?_Haskell - Fatal编程技术网

Haskell 有可能在哈斯克尔中推广方程吗?

Haskell 有可能在哈斯克尔中推广方程吗?,haskell,Haskell,为我对问题的拙劣措辞道歉。我试着寻找答案,但不知道该搜索什么,这使得我很难找到答案 这是一个计算三角形面积的简单函数 triangleArea :: Float -> Float -> Float -> Float triangleArea a b c | (a + b) <= c = error "Not a triangle!" | (a + c) <= b = error "Not a triangle!" | (b

为我对问题的拙劣措辞道歉。我试着寻找答案,但不知道该搜索什么,这使得我很难找到答案

这是一个计算三角形面积的简单函数

triangleArea        :: Float -> Float -> Float -> Float
triangleArea a b c 
    | (a + b) <= c  = error "Not a triangle!"
    | (a + c) <= b  = error "Not a triangle!"
    | (b + c) <= a  = error "Not a triangle!"
    | otherwise     = sqrt (s * (s - a) * (s - b) * (s - c))
        where s     = (a + b + c) / 2

Haskell知道检查这三个参数的每个可能组合。

我认为@behzad.nouri的评论是最好的。有时做一点数学是编程的最好方法。这里有一个关于@melpomene解决方案的有点夸张的扩展,我认为分享它会很有趣。让我们编写一个类似于置换的函数,但它计算组合:

import Control.Arrow (first, second)

-- choose n xs returns a list of tuples, the first component of each having
-- n elements and the second component having the rest, in all combinations
-- (ignoring order within the lists). N.B. this would be faster if implemented
-- using a DList.
choose :: Int -> [a] -> [([a],[a])]
choose 0 xs = [([], xs)]
choose _ [] = []
choose n (x:xs) =
  map (first (x:)) (choose (n-1) xs) ++
  map (second (x:)) (choose n xs)
所以

现在你可以写作了

triangleArea a b c
  | or [ x + y <= z | ([x,y], [z]) <- choose 2 [a,b,c] ] = error ...
triangleareaa a b c
|或者[x+y这里有两个想法

  • 使用现有工具,您可以生成参数的所有排列,并检查它们是否都满足条件。因此:

    import Data.List
    triangleArea a b c
        | any (\[x, y, z] -> x + y <= z) (permutations [a,b,c])
                    = error "Not a triangle!"
        | otherwise = {- ... -}
    
    我们可以使用它构建一个只选择适当元素三元组的函数:

    triples :: [a] -> [(a, a, a)]
    triples xs = do
        (b1, v1, e1) <- zippers xs
        (b2, v2, e2) <- zippers e1
        v3 <- b1 ++ b2 ++ e2
        return (v1, v2, v3)
    
    triples::[a]->[(a,a,a)]
    三元组xs=do
    
    (b1、v1、e1)这并没有解决如何缩短错误检查代码的问题,但您可以通过定义一些具有不变量的新类型来限制重复错误检查的频率。此函数需要进行错误检查,因为您不能信任用户提供构成合理三角形的
    Float
    三元组,如果您继续定义fu这样,您编写的每个三角形相关函数都需要类似的错误检查

    但是,如果定义三角形类型,则在创建三角形时只能检查一次不变量,然后所有其他函数将保证接收有效三角形:

    module Triangle (Triangle(), mkTriangle, area) where
    
    data Triangle a = Triangle a a a deriving Show
    
    mkTriangle :: (Num a, Ord a) => a -> a -> a -> Either String (Triangle a)
    mkTriangle a b c
      | a + b <= c = wrong
      | a + c <= b = wrong
      | b + c <= a = wrong
      | otherwise  = Right $ Triangle a b c
      where wrong  = Left "Not a triangle!"
    
    area :: Floating a => Triangle a -> a
    area (Triangle a b c) = sqrt (s * (s - a) * (s - b) * (s - c))
      where s = (a + b + c) / 2
    
    模块三角形(Triangle(),mkTriangle,area),其中
    数据三角形a=三角形a派生显示
    mkTriangle::(numa,orda)=>a->a->a->任一字符串(三角形a)
    三角形a b c
    
    |a+b好吧,你可以写
    任何[arg1+arg2]你的3个条件相当于
    a+b+c@behzad.nouri你可以用它来发布一个答案
    
    zippers :: [a] -> [([a], a, [a])]
    zippers = go [] where
        go b [] = []
        go b (v:e) = (b, v, e) : go (v:b) e
    
    triples :: [a] -> [(a, a, a)]
    triples xs = do
        (b1, v1, e1) <- zippers xs
        (b2, v2, e2) <- zippers e1
        v3 <- b1 ++ b2 ++ e2
        return (v1, v2, v3)
    
    triangleArea a b c
        | any (\(x, y, z) -> x + y <= z) (triples [a,b,c])
                    = error "Not a triangle!"
        | otherwise = {- ... -}
    
    module Triangle (Triangle(), mkTriangle, area) where
    
    data Triangle a = Triangle a a a deriving Show
    
    mkTriangle :: (Num a, Ord a) => a -> a -> a -> Either String (Triangle a)
    mkTriangle a b c
      | a + b <= c = wrong
      | a + c <= b = wrong
      | b + c <= a = wrong
      | otherwise  = Right $ Triangle a b c
      where wrong  = Left "Not a triangle!"
    
    area :: Floating a => Triangle a -> a
    area (Triangle a b c) = sqrt (s * (s - a) * (s - b) * (s - c))
      where s = (a + b + c) / 2