使用“它”产生的模糊类型变量“a0”

时间:2016-07-22 16:59:01

标签: haskell functional-programming ghc ghci

我有以下函数来返回给定数字的因子对

factorPairs:: (RealFrac a, Floating a, Integral a) => a -> [(a, a)]
factorPairs n = map(\x -> (x, div n x)) [y | y <- [1..(ceiling $ sqrt n)], n `rem` y == 0]

当我在ghci factorPairs 18中调用该函数时,我的运行时错误

   * Ambiguous type variable `a0' arising from a use of `it'
      prevents the constraint `(Floating a0)' from being solved.
      Probable fix: use a type annotation to specify what `a0' should be.
      These potential instances exist:
        instance Floating Double -- Defined in `GHC.Float'
        instance Floating Float -- Defined in `GHC.Float'
    * In the first argument of `print', namely `it'
      In a stmt of an interactive GHCi command: print it

我可以在ghci

中对该函数进行硬编码

map(\x -> (x, div 18 x)) [y | y <- [1..(ceiling $ sqrt 18)], 18 `rem` y == 0]  并没有任何问题,但我似乎无法弄清楚为什么我的功能失败。我相信ghci试图告诉我它无法弄清楚要调用print的类型,但我正在努力寻找解决方案。

2 个答案:

答案 0 :(得分:5)

这与Haskell中重载数字文字的事实有关。当您在map(\x -> (x, div 18 x)) [y | y <- [1..(ceiling $ sqrt 18)], 18 `rem` y == 0]中输入ghci时,18的参数sqrt默认为Double,其他IntegerfactorPairs:: (RealFrac a, Floating a, Integral a) => a -> [(a, a)] factorPairs n = map(\x -> (x, div n x)) [y | y <- [1..(ceiling $ sqrt n)], n `rem` y == 0]

但是,当你写

n

您强制fromIntegral的所有实例只有一种类型。然后,问题变成了没有默认的数字类型(实际上我认为通常是数字类型),它们满足所有这些约束,因此GHC会告诉你关于&#34;可能的实例&#34;它尝试。解决方案是添加factorPairs:: Integral a => a -> [(a, a)] factorPairs n = map(\x -> (x, div n x)) [y | y <- [1..(ceiling $ sqrt $ fromIntegral n)], n `rem` y == 0] 并放宽约束:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace ProPharmacyManagerW.Controls
{
    class IconButton : Button
    {
        public static readonly DependencyProperty ImageProperty = DependencyProperty.Register("Image", typeof(ImageSource), typeof(IconButton), new PropertyMetadata(null));
        public static readonly DependencyProperty ImageHeightProperty = DependencyProperty.Register("ImageHeight", typeof(double), typeof(IconButton), new PropertyMetadata(double.NaN));
        public static readonly DependencyProperty ImageWidthProperty = DependencyProperty.Register("ImageWidth", typeof(double), typeof(IconButton), new PropertyMetadata(double.NaN));
        public static readonly DependencyProperty HoverColorProperty = DependencyProperty.Register("ColorHover", typeof(SolidColorBrush), typeof(IconButton), new PropertyMetadata(Brushes.LightGray));
        public static readonly DependencyProperty PressedColorProperty = DependencyProperty.Register("ColorPressed", typeof(SolidColorBrush), typeof(IconButton), new PropertyMetadata(Brushes.Gray));
        public static readonly DependencyProperty DisabledColorProperty = DependencyProperty.Register("ColorDisabled", typeof(SolidColorBrush), typeof(IconButton), new PropertyMetadata(Brushes.Gray));

        static IconButton()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(IconButton), new FrameworkPropertyMetadata(typeof(IconButton)));
        }

        public ImageSource Image
        {
            get { return (ImageSource)GetValue(ImageProperty); }
            set { SetValue(ImageProperty, value); }
        }

        public double ImageHeight
        {
            get { return (double)GetValue(ImageHeightProperty); }
            set { SetValue(ImageHeightProperty, value); }
        }

        public double ImageWidth
        {
            get { return (double)GetValue(ImageWidthProperty); }
            set { SetValue(ImageWidthProperty, value); }
        }

        public SolidColorBrush ColorHover
        {
            get { return (SolidColorBrush)GetValue(HoverColorProperty); }
            set { SetValue(HoverColorProperty, value); }
        }

        public SolidColorBrush ColorPressed
        {
            get { return (SolidColorBrush)GetValue(PressedColorProperty); }
            set { SetValue(PressedColorProperty, value); }
        }

        public SolidColorBrush ColorDisabled
        {
            get { return (SolidColorBrush)GetValue(DisabledColorProperty); }
            set { SetValue(DisabledColorProperty, value); }
        }
    }
}

答案 1 :(得分:4)

摆脱类型错误的另一种方法是消除sqrt的使用。由于Haskell是懒惰的,你可以简单地迭代[1..n],当你的除数大于你的商时停止。

factorPairs :: Integral a => a -> [(a, a)]
factorPairs n = takeWhile (uncurry (>=)) [ (n `div` d, d) | d <- [1..n], n `mod` d == 0]

uncurry (>=)只是写\(q, d) -> q >= d的一种奇特方式。

如果你以monadic形式写这个,你可以使用divMod来获得商和余数,只需一个函数。

factorPairs n = takeWhile (uncurry (>=)) $ do
                d <- [1..n]
                let (q, r) = n `divMod` d
                guard $ r == 0
                return (q, d)