代码之家  ›  专栏  ›  技术社区  ›  Dave

Haskell:将积分转换为浮点(或浮点)。混合浮点数和整数

  •  1
  • Dave  · 技术社区  · 6 年前

    我仍然很难将我的大脑围绕在哈斯克尔及其类型系统上。我发布了另一个问题: Haskell Converting Int to Float 这当然很有帮助,但我仍然被困在这里。我认为这里有一个更简单的例子:

    ymod2 :: Integral b => b -> [b]
    ymod2 n = map (\y->(y `mod` 2)) [0..n]    
    
    powersOfx :: (Enum b, Floating b) =>  b -> b -> [b]
    powersOfx n x = map (\y->(x**y)) [0..n]
    
    thirdLst :: (Integral a, Enum a, Enum b, Floating b) => a -> b -> [b]    
    thirdLst n x = zipWith (*) (ymod2 n) (powersOfx (fromIntegral n) x)
    

    正如您所看到的,我有一个接受整数(ymod2)的函数和一个接受枚举(Floating)的函数。这两种都在第三阶段使用(通过zipWith)。我传递第三个积分和浮点。我确实尝试将积分更改为浮点,以便在powersOfx中使用。当我将其加载到WinGHCi中时,我得到:

    • Couldn't match type ‘b’ with ‘a’
      ‘b’ is a rigid type variable bound by
        the type signature for:
          thirdLst :: forall a b.
                      (Integral a, Enum a, Enum b, Floating b) =>
                      a -> b -> [b]
       // and quite a bit more which I can post if desired
    

    我尝试过各种排列。我删除了fromIntegral,尝试了不同的类型,但似乎没有任何效果。 我想我的中心问题可能是如何转换类型。我想fromIntegral会做的。我意识到,在这个精心设计的示例中,可以重写powersOfx方法以使用不同的类型。但我的问题仍然存在。这就是如何使这两种方法在压缩时很好地结合在一起。

    谢谢Dave

    使现代化根据Willem的回答,我将thirdLst替换为:

    thirdLst :: (Integral a, Floating b, Enum b) => a -> b -> [b]    
    thirdLst n x = zipWith (*) (map fromIntegral (ymod2 n)) (powersOfx (fromIntegral n) x)
    

    我相信威廉的例子要高得多,未来的读者应该研究他的答案。我认为他的答案是正确的。谢谢Willem!

    2 回复  |  直到 6 年前
        1
  •  4
  •   Mor A.    6 年前

    哈斯克尔(数值)型系统

    我仍然很难将我的大脑围绕在哈斯克尔及其类型系统上。

    我认为 数字的 Haskell中的类型:

    1. 类型之间没有隐式转换(不是数字类型之间,也不是其他类型之间),因此不能隐式转换 Int 到a Float ;
    2. 操作员在 相同的 类型例如 (+) :: Num a => a -> a -> a ,这意味着如果其中一个操作数是 内景 ,则另一个操作数和结果均为 内景 s和
    3. 数值运算符(如 (+) ,则, (-) ,则, (**) )源于 类型类别 例如 (**) :: Fractional a => a -> a -> a 源于 Fractional 类型类。

    导出函数的类型(以及为什么会有问题)

    现在让我们模拟Haskell编译器。定义函数:

    thirdLst n x = zipWith (*) (ymod2 n) (powersOfx (fromIntegral n) x)
    

    我们在这里看到这个函数有两个参数 n x ,所以首先我们假设 thirdLst 具有类型:

    thirdLst :: a -> b -> c
    

    但我们仍然需要通过查看表达式来分析类型。我们看到 ymod2 :: Integral d => d -> [d] (我们这里使用另一个名称,因为它们基本上是不同的变量)函数被调用,这意味着 N a 以及 d ,这意味着 A. D 类型相同,并且 ymod2 n 生成列表 [a] 。我们还必须添加 Integral a 类型,现在我们函数的类型是:

    thirdLst :: Integral a => a -> b -> c
    ymod2 n :: Integral a => [a]
    

    我们还可以在表达式中看到 fromIntegral :: (Integral e, Num f) => e -> f 使用调用 N 作为参数,所以我们得出结论 a ~ e ( A. e 是相同的类型),并且 fromIntegral n 具有类型 Num f => f .我们再次添加 Integral 类型约束到 A. ,但由于它已经以这种方式受到约束 A. 保持不变:

    thirdLst :: Integral a => a -> b -> c
    ymod2 n :: Integral a => [a]
    fromIntegral n :: Num f => f
    

    这个 fromIntegral 表达式只是的子表达式 (powersOfx (fromIntegral n) x) 自从 powersOfx 具有类型 powersOfx :: (Enum g, Floating g) => g -> g -> [g] .因此,我们知道 f ~ g b ~ g ,因此我们知道表达式的结果是 [b] ,我们必须添加 Enum b Floating b 作为约束:

    thirdLst :: (Integral a, Enum b, Floating b) => a -> b -> c
    ymod2 n :: Integral a => [a]
    fromIntegral n :: Num b => b
    powersOfx (fromIntegral n) x :: (Enum b, Floating b) => [b]
    

    这到目前为止没有问题,这两个参数 第三名 ,则, N 十、 有不同的类型,但现在我们使用 zipWith :: (h -> i -> j) -> [h] -> [i] -> [j] 我们使用作为第一个参数 (*) :: Num k => k -> k -> k ,因此我们知道 k ~ h ~ i ~ j 因此 zipWith (*) 具有类型:

    zipWith (*) :: Num k => [k] -> [k] -> [k]
    

    现在问题来了,我们看到 zipWith(*) 需要有 相同的 类型自从 ymod2 n :: Integral a => [a] powersOfx (fromIntegral n) x :: (Enum b, Floating b) => [b] 是我们用于 zipWith(*) 这意味着 k ~ a ~ b 所以 k ,则, A. b 都是相同的类型。现在我们得出结论:

    thirdLst :: (Integral a, Enum a, Floating a, Num a) => a -> a -> [a]
    

    这意味着这两个参数需要具有相同的类型。现在这已经导致了一个重要问题:数字通常不是 完整的 Floating 同时在最常见的数字库中,没有两种数字类型 浮动 完整的 同时因此,这使得该函数非常无用。

    允许更多自由

    因此,我们需要找到更多的泛型函数和更多的自由度。你的 功率OFX 函数为 限制性:由于列表的长度 十、 需要具有相同的类型。我们可以在两种类型独立的情况下构建一个:

    import Data.List(genericTake)
    
    powersOfx :: (Num a, Integral i) => i -> a -> [a]
    powersOfx n x = genericTake (n+1) (iterate (x*) 1)
    

    对于 ymod2 ,您基本上构建了一个具有特定长度的列表 [0, 1, 0, 1, ...] .所以我们可以使用 cycle :: [a] -> [a] 为了这个,还有一个 genericTake (n+1) :

    ymod2 :: (Num a, Integral i) => i -> [a]
    ymod2 n = genericTake (n+1) (cycle [0, 1])
    

    然后我们的功能是:

    thirdLst :: (Num c, Integral a) => a -> c -> [c]
    thirdLst n x = zipWith (*) (ymod2 n) (powersOfx n x)
    
        2
  •  1
  •   MCH    6 年前
    ymod2 :: Integral a => a -> [a]
    ymod2 n = map (\y->(y `mod` 2)) [0..n]    
    
    powersOfx :: (Enum b, Floating b) =>  b -> b -> [b]
    powersOfx n x = map (\y->(x**y)) [0..n]
    
    thirdLst :: (Integral a, Enum b, Floating b) => a -> b -> [b]    
    thirdLst n x = zipWith (*) (fromIntegral <$> ymod2 n) (powersOfx (fromIntegral n) x)